const

const变量在定义时进行初始化。

  1. const int a = 7;
  2. int b = a; // 正确
  3. a = 8; // 错误,不能改变
  • A: const 修饰指针指向的内容,则内容为不可变量。

    1. const int *p = 8;
  • B: const 修饰指针,则指针为不可变量。

    1. int a = 8;
    2. int* const p = &a;
    3. *p = 9; // 正确
    4. int b = 7;
    5. p = &b; // 错误
  • C: const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。

    1. int a = 8;
    2. const int * const p = &a;

作用

  1. 修饰变量,说明该变量不可以被改变;
  2. 修饰指针,分为指向常量的指针(pointer to const)和自身是常量的指针(常量指针,const pointer);
  3. 修饰引用,指向常量的引用(reference to const),用于形参类型,即避免了拷贝,又避免了函数对值的修改;
  4. 修饰成员函数,说明该成员函数内不能修改成员变量。

    const 的指针与引用

  • 指针
    • 指向常量的指针(pointer to const)
    • 自身是常量的指针(常量指针,const pointer)
  • 引用
    • 指向常量的引用(reference to const)
    • 没有 const reference,因为引用本身就是 const pointer
  1. // 类
  2. class A
  3. {
  4. private:
  5. const int a; // 常对象成员,只能在初始化列表赋值
  6. public:
  7. // 构造函数
  8. A() : a(0) { };
  9. A(int x) : a(x) { }; // 初始化列表
  10. // const可用于对重载函数的区分
  11. int getValue(); // 普通成员函数
  12. int getValue() const; // 常成员函数,不得修改类中的任何数据成员的值
  13. };
  14. void function()
  15. {
  16. // 对象
  17. A b; // 普通对象,可以调用全部成员函数、更新常成员变量
  18. const A a; // 常对象,只能调用常成员函数
  19. const A *p = &a; // 指针变量,指向常对象
  20. const A &q = a; // 指向常对象的引用
  21. // 指针
  22. char greeting[] = "Hello";
  23. char* p1 = greeting; // 指针变量,指向字符数组变量
  24. const char* p2 = greeting; // 指针变量,指向字符数组常量(const 后面是 char,说明指向的字符(char)不可改变)
  25. char* const p3 = greeting; // 自身是常量的指针,指向字符数组变量(const 后面是 p3,说明 p3 指针自身不可改变)
  26. const char* const p4 = greeting; // 自身是常量的指针,指向字符数组常量
  27. }
  28. // 函数
  29. void function1(const int Var); // 传递过来的参数在函数内不可变
  30. void function2(const char* Var); // 参数指针所指内容为常量
  31. void function3(char* const Var); // 参数指针为常量
  32. void function4(const int& Var); // 引用参数在函数内为常量
  33. // 函数返回值
  34. const int function5(); // 返回一个常数
  35. const int* function6(); // 返回一个指向常量的指针变量,使用:const int *p = function6();
  36. //比如 在 ClassName 类的 const 成员函数中,this 指针的类型为:const ClassName* const,这说明不能对 this 指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);
  37. int* const function7(); // 返回一个指向变量的常指针,使用:int* const p = function7();比如ClassName *const this意味着不能给this指针赋值

constexpr

constexpr是C++11中新增的关键字,其语义是“常量表达式”,也就是在编译期可求值的表达式。最基础的常量表达式就是字面值或全局变量/函数的地址或sizeof等关键字返回的结果,而其它常量表达式都是由基础表达式通过各种确定的运算得到的。constexpr值可用于enum、switch、数组长度等场合。
constexpr所修饰的变量一定是编译期可求值的,所修饰的函数在其所有参数都是constexpr时,一定会返回constexpr。

constexpr int Inc(int i) {
    return i + 1;
}

constexpr int a = Inc(1); // ok
constexpr int b = Inc(cin.get()); // !error
constexpr int c = a * 2 + 1; // ok

constexpr还能用于修饰类的构造函数,即保证如果提供给该构造函数的参数都是constexpr,那么产生的对象中的所有成员都会是constexpr,该对象也就是constexpr对象了,可用于各种只能使用constexpr的场合。注意,constexpr构造函数必须有一个空的函数体,即所有成员变量的初始化都放到初始化列表中。

struct A {
    constexpr A(int xx, int yy): x(xx), y(yy) {}
    int x, y;
};

constexpr A a(1, 2);
enum {SIZE_X = a.x, SIZE_Y = a.y};

优点

  1. 是一种很强的约束,更好地保证程序的正确语义不被破坏。
  2. 编译器可以在编译期对constexpr的代码进行非常大的优化,比如将用到的constexpr表达式都直接替换成最终结果等。
  3. 相比宏来说,没有额外的开销,但更安全可靠。

参考资料

https://www.cnblogs.com/fuzhe1989/p/3554345.html