Skip to content

Latest commit

 

History

History
46 lines (45 loc) · 5.13 KB

const修饰符.md

File metadata and controls

46 lines (45 loc) · 5.13 KB

被const修饰的东西具有只读的特点

  • const的作用:
  1. 修饰变量:只读变量
    被const修饰的变量必须立即初始化
  2. 修饰对象:不能修改成员变量的值,不能调用非const函数
    结合第9点,若使用const修饰一个对象,则该对象里的this指针是一个指向const对象的const指针,因此不能修改成员变量的值。而非const成员行数要求隐性传入的this指针是一个指向对象的const指针,这里发生了参数不匹配的问题,因此不能调用
  3. 指向const变量的指针:指针指向的是拥有const变量的地址,指向内容不可变,指向可变(const int* p ,p可以不断调整,即改变指向,但*p不能调整,即不能通过指针来改变const变量)
    编译器是通过静态判断指针类型来识别指针是否为指向const变量的指针的,即即使指向const变量的指针指向乐一个非const变量的地址,也不可以通过引用指针的方式对该变量进行修改,而若用一个普通指针指向一个const变量的地址,则可以通过引用指针的方式对该变量进行修改,但是,该const变量会根据编译器的优化程度决定其值是否发生改变,在一些较低版本的编译器上有可能该值会发生改变。
    因此,尽量使用const变量来替代宏定义来定义变量:使用const定义变量可以让编译器帮我们进行类型检查,而且在引用变量时会直接用const变量进行替换,并不会发生一次变量访问,即和宏定义一样具有相同的执行效率
  4. const指针:指向内容可变,指向不可变(int * const p ,p的指向一旦赋值不能发生改变)
  5. 指向const变量的const指针:指向内容不可变,指向也不可变(const int * const p)
  6. const变量做函数参数:函数内部不能改变此参数
  7. const作为函数返回值:返回const引用
  8. const作为类的成员变量:必须在初始化列表初始化,之后不能改变;静态const成员变量需要在类外单独初始化
  9. const成员函数:不能修改任何成员变量(传给const成员函数的this指针是指向const对象的const指针)
    在一个对象里面,一个this指针被隐形地当作参数传递给行数,而这个this指针是一个指向对象地const指针,其指向不能发生改变。而传递给const成员行数地this指针是一个指向const对象的const指针,因此不能够对成员变量进行修改
  • const的一些tricky的用法:
  1. 默认情况下const修饰的对象仅在文件内有效,其他文件想要访问该对象必须自身单独定义一个对象并进行初始化,相当于是const修饰的对象对于文件而言是私有的。然而,如果我们希望在一个文件内使用const定义一个变量而且这个变量有在其余文件也能被访问到的必要,则我们需要使用extern关键字进行修饰:
    在file.cc文件中使用extern const int val = 10;初始化val变量,在file.h中使用extern const int val;声明变量val并不是当前文件所独有的,与文件file.cc中是同一个
  2. const的引用:把引用绑定到const对象上,简称常量引用
    const int i = 10;
    const int &ri = i;
    • 但是不能用一个非常量引用指向一个常量对象:int &r2 = i,这是不允许的行为
    • 引用时引用类型与被引用对象的类型不一致的一种情况:在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成应用的类型即可:
    int i = 10;
    const int& ri = i;
    
    double p = 3,14;
    // 等价于先使用const int temp = p即由双精度浮点数生成一个临时的整型变量,再const int& rp = temp绑定这个临时变量
    const int& rp = p; 
    • 当对于const的引用绑定了一个并非const的对象时,可以通过修改这个非const的对象的值来改变这个const引用的值,但是不能直接通过修改这个const引用的对象来修改这个非const对象的值
    int i = 10;
    const int & ri = i;
    i = 5;
    cout << i << " " << ri << endl; // 输出结果为: 5 5
  3. constexpr 变量
    在一个复杂的系统中很难分辨一个初始值到底是不是常量表达式,即使对于这个初始值使用了const修饰也是如此。c++11新标准规定允许将变量声明为constexpr类型的以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定已是一个常量,而且必须使用常量表达式来初始化。
    一个constexpr指针必须是nullptr或者0或者存储于某个固定地址中的对象。因此,在函数体中(包括main函数)不能使用constexpr来修饰变量(函数体内定义的变量往往不具有固定地址)。而且被constexpr修饰的指针与const不同,const可以修饰指针指向的变量,即指向const变量的指针,而使用相同方法而将修饰符由const替换成constexpr会得到一个常量指针,即其指向不能够改变。
    reference