0 引言
const is widely used in C++, this blog will record common usage of const. Including:
- const values(number variable, string variable, stl variable, ...), const value 是一个值,可以正常用于拷贝,初始化其他变量等,仅仅在执行改变该const val的时候才会触发作用。由于const值不能被改变,因此标准中规定必须要对const value进行初始化。 一般有两种方法对const值进行初始化:
- 声明时初始化
- 函数中声明为const的形参在函数被调用时会得到参数值
- pointer to const value(指向常量的指针), 不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。 low-level const, pointer can be changed but not variable it pointed.
- const double pi = 3.14; const double *ptr = π ///< 意为解引用ptr (*ptr) 会得到一个const double的value.
- const pointer to value, 必须初始化,而且一旦初始化完成,则它的值(即地址)就不能再改变了。 top-level point, pointer cannot be changed but not variable.
- int errNumb = 0; int *const curErr = &errNum; ///< 意为解引用const curErr(*curErr) 得到一个可变的int值,但指针本身的值不能变化。
- const pointer to const value
- int const *const cpci; ///< both pointer and the value it pointer is const.
reference:
Microsoft Dos: https://docs.microsoft.com/en-us/cpp/cpp/const-cpp?view=msvc-160
const error: https://stackoverflow.com/questions/26963510/error-passing-const-as-this-argument-of-discards-qualifiers
C和指针》
1 example of top && low level pointer && const reference
1.1 const pointer to value: 表示指针本身是一个常量, 可以调用class member function 对 class member var进行修改
这种形式可以调用class member function,并且允许改变class member var 的值, 但是不能改变指针本身的值(即地址)
demo:
#include <iostream> class Var { public: Var(const int *a) {} Var(const int &size) { d_size = size; } int getSize() const { return d_size; } ///< https://stackoverflow.com/questions/3141087/what-is-meant-with-const-at-end-of-function-declaration
///< is equal as int getSize(const Var *this){resutn d_size}, which means that getSize is not allowed to change value by a const this pointer. void setSize(const int &size) { d_size = size; } private: int d_size; }; void TestConstRef() { Var aa(77); Var *const tempVar = &aa; ///< 解引用const tempVar得到一个可变的Var object,可以通过tempVar引用Var的函数对aa对象进行修改 std::cout << "aa.size = " << tempVar->getSize() << std::endl; tempVar->setSize(89); std::cout << "aa.size = " << tempVar->getSize() << std::endl; } int main(){ TestConstRef(); return 0; }
result
Output:
aa.size = 77 aa.size = 89
1.2 pointer to const: 指针本身不是一个常量,指针指向的对象是一个常量
这种形式只能调用被const限定的 (at the end of declaration) class member function。 不能修改指针指向的对象的class member var.
demo
#include <iostream> class Var { public: Var(const int &size) { d_size = size; } int getSize()const { return d_size; } void setSize(const int &size) { d_size = size; } private: int d_size; }; void ChangeSize(const Var *aa) { ///< aa is a pointer to a const, aa itself can be changed, but var it pointed can not be changed. aa->setSize(89); ///< equal as setSize(const Var *this, const int &size) {d_size = size}, now that aa is a pointer to a const this pointer, setSize is not allowed to change value of aa. std::cout << "aa.size = " << aa->getSize() << std::endl; } void TestConstRef() { Var aa(77); std::cout << "aa.size = " << aa.getSize() << std::endl; ChangeSize(&aa); } int main(){ TestConstRef(); return 0; }
result: not supported to pass pointer to const when you need to change content of var it pointed.
Compile error:
const_test.cpp: In function ‘void ChangeSize(const Var*)’: const_test.cpp:16:19: error: passing ‘const Var’ as ‘this’ argument of ‘void Var::setSize(const int&)’ discards qualifiers [-fpermissive] aa->setSize(89);
1.3 const reference
如果确定了调用的class member function不会对class member var进行赋值、更改的话,就应该用这种形式。
demo:
#include <iostream> class Var { public: Var(const int &size) { d_size = size; } int getSize()const { return d_size; } ///< function called by const reference object should be limited by const at the end, or it will report an error like
///< "error: passing ‘const Var’ as ‘this’ argument of ‘int Var::getSize()’ discards qualifiers [-fpermissive]"
void setSize(const int& size) { d_size = size; }
private: int d_size; }; void noChangeSize(const Var &aa) { aa.setSize(89); ///< not supported. first run: std::cout << "aa.size = " << aa.getSize() << std::endl; ///< second run } void TestConstRef() { Var aa(77); std::cout << "aa.size = " << aa.getSize() << std::endl; noChangeSize(aa); } int main(){ TestConstRef(); return 0; }
result
first run output:
test.cpp: In function ‘void noChangeSize(const Var&)’:
test.cpp:14:18: error: passing ‘const Var’ as ‘this’ argument of ‘void Var::setSize(const int&)’ discards qualifiers [-fpermissive]
aa.setSize(89); ///< not supported.
second run output
aa.size = 77 aa.size = 77
2 summary
- 1.1 is not commonly used, 1.2 and 1.3 is commonly used to protect val pointed by pointer.
- 1.1 can be replaced by pointer itself, which is more common.
- 1.3 is the most safe usage. If you can choose to use const reference, do not hesitate.