2.4 const 限定符

关键字const  :  值不能被改变 必须初始化

const int bufSize = 512;   //输入缓冲区大小,将bufSize定义成了一个常量
bufSize = 512//错误:试图向const对象写值


const int i = get_size();  //正确:运行时初始化
const int j = 42;          //正确;编译时初始化
const int k;               //错误:k是一个未经初始化的常量
int i = 42const int ci = i;
int j = ci;
//用一个对象取初始化令一个对象,则它们是不是const无关紧要

 

默认状态下,const对象仅在文件内有效

如果想在多个文件间共享const对象,必须在变量的定义前添加extern关键字。

//file_1.cc定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufSize = fun();
//file_1.h头文件
extern const int bufSize;//与file_1.cc中定义的bufSize是同一个

 2.4.1 const的引用

把引用绑定到const对象上,对常量的引用不能被用作修改它所绑定的对象。

const int ci = 1024;
const int &r1 = ci;

r1 = 42;                         //错误。r1是对常量的引用。
int &r2 = ci;                    //错误。试图让一个非常量引用指向一个常量对象。

初始化和对const的引用

int i = 42;
const int &r1 = i;                     
const int &r2 = 42;
const int &r3 = r1 * 2;
int &r4 = r1 * 2;                    //F.     r4是一个普通的非常量引用。


//初始化常量引用时允许用任意表达式作为初始值。

2.4.2 指针和const

类似于常量引用,指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。

const double pi = 3.14
double *ptr = π                   //F. ptr是一个普通指针 
const double *cptr = π
*cptr = 42;                             //F. 不能给*cptr赋值    

//允许令一个指向常量的指针指向一个非常量。
double dval = 3.14;
cptr = &dval;                           //T.但不能通过cptr改变dval的值。

const指针

指针是对象,允许把指针本身定为常量。常量指针必须初始化,且存放在指针中的地址(即指针的值)不能再改变。把*放在const关键字之前用以说明指针是一个常量。

int errNumb = 0;
int *const curErr = &errNumb;          //curErr将一直指向errNumb
const double pi = 3.14;
const double *const pip = π         //pip是一个指向常量对象的常量指针

 * 从右向左读 此例中,离curErr最近的是const,意味着curErr本身是一常量对象,对象的类型由声明符的其余部分确定。

2.4.3 顶层const

顶层const:指针本身是个常量。

底层const:指针所指对象是常量。

int i = 0;
int *const p1 = &i;                               //不能改变p1的值,顶层const
const int ci = 42;                                //不能改变ci的值,顶层const
const int *p2 = &ci;                              //允许改变p2的值,底层const
const int *const p3 = p2;                         //靠右顶层,靠左底层
const int &r = ci;                                //用于声明引用的const都是底层const


//执行对象的拷贝操作时,顶层const不受什么影响
i = ci;                              //T 。ci是一个顶层const,对此操作无影响。
p2 = p3;                             //T 。 p2和p3指向的对象类型相同,p3顶层const部分无影响。

 

底层const的限制不能忽视。当执行对象的拷贝操作时,两个对象必须具有相同底层const资格,或者两个对象的数据类型必须能够转换。非常量可以转换为常量,反之不行。

int *p = p3;               //F。p3包含底层const
p2 = p3;                   //T 。
p2 = &i;                   //T 。int*能够转化为const int* 
int &r = ci;               //F 。普通的int&不能绑定到int常量上
const int &r2 = i;         //T 。const int& 可以绑定到一个普通int上

 

2.4.4 constexpr和常量表达式

 常量表达式:值不会改变并且在编译过程就能得到计算结果的表达式。

const int max_files = 20;
const int limit = max_files + 1;
int staff_size = 27;                          //不是。
const int sz = get_size();                    //不是。

 constexpr变量

将变量声明为constexpr类型以便编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。

constexpr int mf = 20;                //20是常量表达式
constexpr int limit = mf + 1;         //mf+1是常量表达式
constexpr int sz = size();            //只有当size是一个constexpr函数时才是一条正确的声明语句

  一般来说,如果认定变量是一个常量表达式,就把它声明成constexpr类型。

 

指针和constexpr

一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。

const int *p = nullptr;                   //p是一个指向整型常量的指针
constexpr int *q = nullptr;               //q是一个指向整数的常量指针,顶层

 

constexpr int *np = nullptr;          //np是指向整形的常量指针,值为空
int j = 0;
constexpr int i = 42;                 //i的类型是整形常量
//i和j都必须定义在函数体之外
constexpr const int *p = &i;          //p是常量指针,指向整型常量i
constexpr int *p1 = &j;               //p1是常量指针,指向整数j

 

posted @ 2017-05-23 20:52  1ww3  阅读(179)  评论(0)    收藏  举报