C++ const 常量

const 常量 

定义义后就不能被修改,所以定义时必须初始化:const std::string hi = "hello!";

const 对象作用域

  • 在全局作用域定义的非const对象在整个程序中都可以访问,默认为extern. [code1]
  • const对象默认为文件的局部变量,要使const变量能够在其他的文件中访问,必须地指定它为extern. [code2]

常量表达式

  • const expression是指值不会改变并且在编译过程就能得到计算结果的表达式
  • 一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定 [code4]
  • 字面值属于常量表达式
  • 用常量表达式初始化的const对象也是常量表达式.

一些const在头文件中的定义

  • 如果const变量是用常量表达式初始化的,那么它应该在头文件中定义(原因类似C的宏#define)
  • 如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义该const变量应该在一个源文件中定义并初始化,应在头文件中为它添加extern声明,以使其能被多个文件共享

引用

  • 不能定义引用类型的引用,但可以定义任何其他类型的引用.
  • 引用必须用与该引用同类型的对象初始化.
  • 必须在定义引用时进行初始化,初始化后可以赋值,但是不能修改引用的指向.

const 引用

  • 指向const对象的引用
  • 普通引用不能绑定const对象
  • const引用则可以绑定到不同但相关的类型的对象或绑定到右值. [code3]
  • 非const引用只能绑定到与该引用同类型的对象. code[3]

const和指针

指向const对象的指针(const int *ptr)

  • 允许给 ptr 重新赋值,使其指向另一个 const 对象,但不能通过 ptr 修改其所指对象的值.
  • 不能使用 void* 指针保存 const 对象的地址,必须使用 const void* 
  • 允许把非 const 对象的地址赋给指向 const 对象的指针

const指针

  • int  *const curErr.从右向左把上述定义语句读作“curErr 是指向 int 型对象的 const 指针”
  • 与任何 const 量一样,const 指针也必须在定义时初始化. 且初始化过后不能指向另外一个对象

指向 const 对象的 const 指针 

  • const double pi = 3.14159;const double *const pi_ptr = π
  • 既不能修改 pi_ptr 所指向对象的值,也不允许修改该指针的指向.
  • 从右向左阅读上述声明语句:“pi_ptr 首先是一个 const 指针,指向 double 类型的 const 对象”。

typedef和指针

  • typedef string *pstring;const pstring cstr;==string *const cstr;
  • 声明 const pstring 时,const 修饰的是 pstring 的类型,这是一个指针。因此,该声明语句应该是把cstr 定义为指向 string 类型对象的 const 指针
  • const 限定符既可以放在类型前也可以放在类型后。string const s1; == const string s2; [Code5]

const和成员函数

  • 将成员函数声明为常量double avg_price() const;
  • const 成员不能改变其所操作的对象的数据成员
  • const 必须同时出现在声明和定义中,若只出现在其中一处,就会出现一个编译时错误。
  • 从 const 成员函数返回 *this

    • 在普通的非 const 成员函数中,this 的类型是一个指向类类型的 const 指针,可以改变 this 所指向的值,但不能改变 this 所保存的地址。

    • 在 const 成员函数中,this 的类型是一个指向 const 类类型对象的 const 指针。既不能改变 this 所指向的对象,也不能改变 this 所保存的地址。

    • 不能从 const 成员函数返回指向类对象的普通引用。const 成员函数只能返回 *this 作为一个 const 引用。


const与成员函数重载

  • Screen& display(std::ostream &os){ do_display(os); return *this; }
  • const Screen& display(std::ostream &os) const{ do_display(os); return *this; }

const与迭代器

  • const_iterator:只能用于读取容器内的元素,但不能改变其值

=====
Code1.在全局作用域定义的非const对象

[cpp]  view plain  copy
 print ?
  1. // file_1.cc  
  2. int counter; // definition  
  3. // file_2.cc  
  4. extern int counter; // uses counter from file_1  
  5. ++counter;  
  6. // increments counter defined in file_1  

Code2.在全局作用域定义的const对象

[cpp]  view plain  copy
 print ?
  1. // file_1.cc  
  2. // defines and initializes a const that is accessible to other files  
  3. extern const int bufSize = fcn();  
  4. // file_2.cc  
  5. extern const int bufSize; // uses bufSize from file_1,extern 标志着bufSize 是一个声明,所以没有初始化式  
  6. // uses bufSize defined in file_1  
  7. for (int index = 0; index != bufSize; ++index)  
  8. // ...  

Code3.const引用则可以绑定到不同但相关的类型的对象或绑定到右值

[cpp]  view plain  copy
 print ?
  1. /*const 引用可以初始化为不同类型的对象或者初始化为右值,如字面值常量:*/  
  2. int i = 42;  
  3. // legal for const references only  
  4. const int &r = 42;  
  5. const int &r2 = r + i;  
  6.   
  7. /*同样的初始化对于非 const 引用却是不合法的,而且会导致编译时错误。其原因非常微妙,值得解释一下。 
  8. 观察将引用绑定到不同的类型时所发生的事情,最容易理解上述行为。假如我们编写*/  
  9. double dval = 3.14;  
  10. const int &ri = dval;  
  11.   
  12. /*编译器会把这些代码转换成如以下形式的编码:*/  
  13. int temp = dval;  
  14. const int &ri = temp;  
  15. // create temporary int from the double  
  16. // bind ri to that temporary  
  17.   
  18. /*如果 ri 不是 const,那么可以给 ri 赋一新值。这样做不会修改 dval,而是修改了 temp。期望对 ri 的赋值会修改 dval 的程序员会发现 dval 并没 
  19. 89有被修改。仅允许 const 引用绑定到需要临时使用的值完全避免了这个问题,因为 const 引用是只读的。*/  

Code4. 一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定

[cpp]  view plain  copy
 print ?
  1. const int max_files = 20; // max_files是常量表达式   
  2. const int limit = max_files + 1; // limit是常量表达式   
  3. int staff_size = 27; // staff_size不是常量表达式   
  4. const int sz = get_size(); // sz不是常量表达式   
  5. /*尽管staff_size的初始值是个字面值常量,但由于它的数据类型只是一个普通int而非const int,所以它不属于常量表达式。另一方面,尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式。*/  

Code5.const 限定符既可以放在类型前也可以放在类型后

[cpp]  view plain  copy
 print ?
  1. string s;  
  2. typedef string *pstring;  
  3.   
  4. //下面三种声明是等价的  
  5. const pstring cstr1 = &s;   
  6. pstring const cstr2 = &s;   
  7. string *const cstr3 = &s;   

From:http://blog.csdn.net/liufei_learning/article/details/21219963
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值