Thinking in C++ Notes(8)

Chapter 8: Constants
Value substitution

  • preprocessor simply does text replacement and has no concept nor facility for type checking.
  • You should always use const instead of #define value substitution.
  • Normally, the C++ compiler avoids creating storage for a const, but instead holds the definition in its symbol table.
  • When you use extern with const, you force storage to be allocated and constant folding is prevented.
  • When using const for aggregates, the const value cannot be used at compile time.

    const int i[]={1,2,3,4};
    float f[i[2]];//Illegal

  • Differences with C:
    • const in C:
      • "an ordinary variable that cannot be changed."
      • always occupies storage and its name is global
      • cannot be treated as a compile-time constant
    • C defaults to external linkage for consts, C++ defaults to internal linkage for consts.

Pointer:

  • Pointer to const

    const int* u;
    int const* u;

    u is a pointer, which point to a const int.
    u can be a lvalue while *u cannot.

  • const pointer

    int d=1;
    int* const w=&d;

    w is a pointer, which is const, that points to an int.
    *w can be a lvalue while w cannot.
    const value must be initialized at the definition.

Assignment and type checking

  • you can assign a non-const object to a const pointer, but you cannot assign a const object to a non-const pointer.
    but you can "casting away constness":

    const int e=2;
    int* w=(int*)&e; //Legal but bad practice

  • a problem:

    char* cp="hello";
    /* this is technically an error because you assign a const array address to an non-const pointer, but the compiler will accept it without complaint, you modify the array through cp is a runtime error */
    char p[]="world";// if you want modify the string, define it like this

Function arguments and return values

  • when passing objects by values, specifying const has no meaning.
    to avoid confusion to the caller, you can make the argument a const inside the function by const reference.
  • returning consts by value has no meaning for built-in types.
    return a const value means it cannot be an lvalue(cannot be assigned or modified)
  • In C++, your first choice when passing an argument is to pass by const reference

Const in classes

  • const inside a class means “This is constant for the lifetime of the object.”
    However, each different object may contain a different value for that constant.
  • constructor initializer list: const data member must be initialized in the list
  • static const of a built-in type can be treated as a compile-time constant.
    static const member must be initialized at the point of definition.
  • “enum hack”
    define an untagged enum in your class then you can use enum value as compile-time constant.

    class Bunch {
        enum { size = 1000 };
        int i[size];
    };

  • mutable:
    bitwise const: every bit in the object is pemanent.
    logical const: although the entire object is conceptually constant, there may be changes on a member-by-member basis.
    2 way to change a data member from within a const member function:
    1. casting away constness(cast “this” pointer)
    2. use mutable keyword to specify the data member may be changed inside a const object.

Volatile
    volatile means “this data may change outside the knowledge of the compiler.”(multi-task,multi-thread,interrupts)

Comments