C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。

  • 一、const常量的初始化

    int main(){
    	int a1 = 1; 	      // 非常量,可以改变其值
    	a1 = 2; 	    // 此时a1的值为2
    	const int a2;		  // 错误,const常量必须初始化
    	const int a2 = a1; 	  // 正确
    	a2 = 0; 	          // 错误,const常量不可改变
    }
    
  • 二、const引用

    1、对常量的const引用
    对const常量的引用,只能是const引用

    const int ci = 1024;     // 初始化常量ci
    
    const int &r1 = ci;	 // 正确,用常量引用绑定常量ci
    int &r2 = ci; 		 // 错误,试图用一个非常量引用绑定一个常量对象
    

    2、对非常量对象的const引用
    对非常量对象可以用一个常量引用绑定它,并且不可通过常量引用去改变原变量的值。但是被绑定的非常量对象是可变的,并且改变后其const引用也会改变。

    int i = 42;			// 定义变量i=42
    const int &r1 = i;	// 正确,定义常量引用r1,并绑定到变量i上
    const int &r2 = 42;	// 正确,定义常量引用r2
    const int &r3 = r1 * 2;	// 正确,定义常量引用r3
    int &r4 = r1 * 2;	// 错误,视图用非常量引用绑定到常量上
    
    int &r5 = i;  
    r5 = 1;  // 正确,用非常量的引用绑定变量i并改变i的值为1
    r1 = 42; // 错误,不能通过常量引用改变原变量,此时r1=1
    
  • 三、const和指针

    (1)只有一个const,如果const位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,可以指向其他的内存单元。

    (2)只有一个const,如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址;指针所指的数据可以通过解引用修改。

    (3)两个const,*左右各一个,表示指针和指针所指数据都不能修改。

    int a1 = 1;
    const int *r1 = &a1;	// (1)const位于*左侧
    int const *r2 = &a1;	// (1)同上
    int *const r3 = &a1;	// (2)const位于*右侧
    const int *const r4 = &a1; // (3)*左右各一个const
    int const *const r5 = &a1; // (3)同上
    

    值得一提的是,在(1)中所说,const位于*左侧时表示指针所指数据为常量,而事实上r1指向的a1是变量,const只是限定了r1对a1的权限,a1本身是否可变与r1无关。

    顶层const和底层const:
    顶层const表示指针本身是个常量(即上述2),而底层const指的是指针所指的是一个常量(上述1)。

  • 四、const引用和const指针

    1、const的修饰作用实际上是给引用和指针设置的权限,也就是说const引用和const指针(底层)不能用于修改其绑定的变量。而变量本身是否能修改要看绑定的是否是const修饰的常量。
    2、对于const修饰的常量进行引用和指针的绑定时,必须是const引用和const指针(底层)。
    3、而对非常量进行引用和指针的绑定时,可以是const的也可以是非const(也就成了普通的引用和指针)的。

  • 五、const成员函数

    首先const成员函数的定义方法是在成员函数的参数列表后紧跟const关键字。C++primer上对此处const的作用定义为:修改隐式指针this指针的类型。
    默认情况下,this指针的类型是:指向类类型非常量版本的常量指针。以书中的Sales_data类举例,this的类型为Sales_data *const。根据(三)中我们的总结,对于指向非常量类型的指针const,我们不能把它绑定到一个常量对象上,也就是说——不能在一个常量对象上调用普通的成员函数。
    此时,常成员函数的作用就体现出来了,const关键字隐式的把非常量版本的指针,修改成了常量版本——const Sales_data *const。由此,得出如下几个结论:
    ① 常量对象,以及常量对象的引用或指针都只能调用常量成员函数
    ② 非常量对象可以调用常量成员函数,但常量成员函数不改变对象中数据成员的值
    ③ 一个例外,用mutable(意为易变的,其承诺被修饰的变量永远可变)修饰的成员变量,可以被常量成员函数修改

 posted on 2017-06-16 18:18  Bill_LHR  阅读(246)  评论(0编辑  收藏  举报