C++ - 指针、引用和const

指针和引用的相同点– 都是复合类型,实现对其他对象的间接访问。

指针和引用的不同点 – 

1) 指针本身就是一个对象,允许赋值和拷贝,在生命周期内可以先后指向不同的对象;引用不是对象,只是给已存在对象绑定的一个别名,不能重新绑定到另外一个对象上。

2) 指针无须在定义时赋值,在块作用域内定义的指针如果没有被初始化将拥有一个不确定的值(和其他内置类型一样);引用必须初始化,初始化完成后将与对象一直绑定。

 

不能定义指向引用的对象,因为引用不是对象,没有实际地址。但可以定义对指针的引用。

int *p;
int *&r = p; //r是对指针p的引用(从右向左阅读,r为引用,引用的对象是指针。)

 

生成空指针的几种方法(建议使用nullptr)

int *p1 = nullptr; //1. C++11引入特殊类型字面值nullptr。
int *p2 = 0; //2
int *p3 = NULL; //3. cstdlib中定义的预处理变量

 

void* 指针

可存放任意对象的地址,但并不知道对象的类型,所以不能直接操作所指的对象。

 

const对象必须初始化,一旦创建后其值不再改变。

 

默认情况下const对象只在当前文件内有效。当多个文件中出现同名const变量时其实等同于分别定义了多个独立的变量。

如果需要在文件间共享一个const变量(i.e. 只在一个文件中定义,在其他文件中声明并使用),则在声明和定义中都使用extern关键字,且只定义一次。

 

Reference to const

对常量的引用(reference to const):绑定到const对象上的引用。可以绑定到const或非const对象上只是不允许通过该引用修改所指对象的值),但普通引用不能绑定到const对象上。

a.k.a. 常量引用 (只是简称,严格来说并不存在常量引用,因为引用不是一个对象。)

const int ci = 1024;  
const int &r1 = ci; 
r1 = 42; //错误 
int &r2 = ci; //错误,非const引用不能绑定到const对象上
int i=42;
cons tint &r1 = i; //正确,允许将const引用绑定到普通对象上

初始化对const的引用时允许用任意表达式作为初始值,只要该表达式结果能转换成引用的类型即可。

 

Pointer to const & const pointer

指向常量的指针(pointer to const):指向const对象的指针,可以指向const或非const对象(只是不允许通过该指针修改所指对象的值)。

const double pi = 3.14;
const double *cptr = π
*cptr = 42; //错误

常量指针(const pointer): 指针本身定位常量,将指针本身定为常量(必须初始化,初始化后值不再改变)。*放在const关键字前,说明const的是指针本身。

int errNumb = 0;
int *const curErr = &errNumb; //从右向左阅读,本身是一个常量对象,类型为常量指针。
const double pi = 3.14159;
const double *const pip = π //从右向左阅读,pip本身是一个常量指针,指向double常量。

 

顶层&底层const

顶层const (top-level const)对象本身是常量,值不能改变。E.g. const pointer.

底层const (low-level const): 指针/引用所指对象是常量。E.g. pointer to const. 用于声明引用的const都是底层const。

int i=0;
int *const p1 = &i; //顶层, pi的值不能改变
const int ci = 42; //顶层,ci的值不能改变
const int *p2 = &ci; //底层,p2的值允许改变
const int * const p3 = p2; //左边的const为底层,右边的const为顶层
const int &r = ci; //底层

顶层const执行拷贝操作时不受影响,因为不会改变被拷贝对象的值;

底层const执行对象拷贝操作时要求拷入拷出对象必须具有相同的底层const资格。(等号右边的非const可以转换为const,但反之不行。 )

int *p = p3; //错误,p3包含底层, p没有
p2 = p3; //正确,p2和p3都是底层
p2 = &i; // 正确,int*能转换为const int*

 

const expression

常量表达式(const expression): 值不会改变并且在编译过程中就能得到计算结果的表达式。E.g. 字面值;用常量表达式初始化的const对象。

一个对象/表达式是否为常量表达式由数据类型和初始值共同决定。

const int max_files = 20; // max_files是
const int limit = max_files+1; // limit是
int staff_size = 27; // 因为数据类型非const, staff_size不是
const int sz = get_size(); // 因为具体值要到运行时才能获得,sz不是

C++11允许将变量声明为constexpr类型,声明为constexpr的变量一定是常量且必须用常量表达式初始化。允许定义一种constexpr函数用于初始化constexpr变量,使之在编译时就可以计算结果。

constexpr int mf = 20;
const expr int limit = mf+1;
const expr int sz = size(): // 只有当size是一个constexpr函数时才是一条正确声明

如果认定一个变量时一个常量表达式,就可以把它声明为constexpr类型。

constexpr指针的初始值必须是nullptr或0,或存储于某个固定地址中的对象(定义于所有函数体以外的对象,或有效范围超出函数本身的变量)。

如果在constexpr声明中定义了一个指针,constexpr仅对指针有效,与所指对象无关,既可指向const也可指向非const。

const int *p = nullptr; //指向int常量的指针
constexpr int *q = nullptr; //指向int的常量指针,顶层const

 

posted @ 2018-11-05 16:32  丹尼尔奥利瓦  阅读(233)  评论(0编辑  收藏  举报