-
指针和const关系的基础知识(英文更容易理解)
一级指针和const的使用
int *p; //pointer p to int int const *p; //pointer p to const int int *const p; //const pointer p to int int const *const p; //const pointer p to const int
需要注意的是以下表达的意思是相同的
const int *p; == int const *p;
const int * const p; == int const * const p;二级指针和const的使用
int **p; //pointer p to pointer to int int * *const p; // a const pointer to a pointer to an int int *const *p; //a pointer to a const pointer to an int int const **p; // a pointer to a pointer to a const int int *const *const p; // a const pointer to a const pointer to an int
-
指针和const的使用
可以令指针指向常量或者非常量,最重要的一点就是指向常量的指针(pointer to const)不能用于改变其所指对象的值,如
const double pi = 3.14; double *ptr = π //错误:ptr是一个普通指针,不能用于指向常量 const double *cptr = π //正确:cptr可以指向一个双精度常量 *cptr = 42; //错误:不能修改*cptr的值
在使用const指针(即常量指针)时,必须首先对其进行初始化,一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了,把*放在const关键字之前用以说明指针是一个常量,即不变的是指针本身的值而非指向的那个值,所以常量指针可以指向非常量变量,例如
int errNum = 0; int *const curErr = &errNum; //curErr将一直指向errNum
-
顶层const和底层const
理解了第2点就很容易理解顶层和底层const了,都是对指针和常量而言的:
顶层const:指针本身是一个常量。
底层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是顶层const,左边的是底层const
-
在函数传参中const的形参和实参转换
当用实参初始化形参时会忽略掉顶层const。换句话说,形参的顶层const会被忽略掉。当形参有顶层const时,传给它常量对象或者非常量对象都是可以的,如以下函数既能传以恶搞常量i也能传一个非常量i,但是不能不能在函数中进行修好:
void func(const int i) { /* func 能够读取i,但是不能修改i*/}
-
一个栗子用于理解
class A { }; void f(const A **p) { printf("f\n"); } void g(const A *const *p) { printf("g\n"); } void k(const A *&p) { printf("k\n"); } int main() { const A *ca = new A(); A *a = new A(); A **p = &a; k(ca); f(p); //出错 g(p); return 0; }
运行上面的代码可以看到f函数是错误的,报错是error: invalid conversion from ‘A**’ to ‘const A**’
对于k函数来说,很简单,形参就是一个const A*类型的引用,实参ca可以用于初始化该形参,k运行正常
对于f函数来说,它的形参是一个二级指针p,更细致的解释:非常量指针p指向一个非常量指针,被指向的非常量指针又指向一个常量A(a pointer to a pointer to a const A),细想一下就可以发现问题所在了,第二个指针是非常量的,它不能用于指向一个常量对象A,所以问题就处在这里。
对于g函数分析下来和f函数同理,在这里就不再赘述了。
更复杂的一些例子,比如说
A ***p; //正确 const A *** p; //错误 const A **const *p; //错误 const A *const *const *p; //正确 A *const *const *p; //正确 A *const **p; //错误
按照上面的规律其实很容易就分析出对错,最主要的一点就是普通指针不能用于指向常量对象。
C++之指针和常量的使用
最新推荐文章于 2023-11-04 17:19:20 发布