在写 C/C++选择题的时候,const指针这一块挺让我头疼的,所以将一些知识点和题目整理如下。
const
先讲一下const的作用:
- 修饰变量,说明该变量不可以被改变;
- 修饰指针,分为指向常量的指针和指针常量;
- 常量引用,经常用于形参类型,即避免了拷贝,又避免了函数对值的修改;
- 修饰成员函数,说明该成员函数内不能修改成员变量。
下面主要讨论下后三点。
指向常量的指针和常量指针
先举个例子:
1 | const int *p1; //指向int型常量的指针,int型常量的值不能修改 |
区别是指向常量的指针还是指针常量,需要注意 const 和 * 的位置。关键字const的右边为const修饰的对象。从左往右读,如果先 * 再 const,为常量指针;如果先 const 再 *,为指向常量的指针。
常量引用
常量引用即 “const &”,使用常量引用需遵守以下两个原则:
1.对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”。例如,类的拷贝构造函数必须使用“const 引用”。
1 | class A { |
如果在Visual Studio和GCC中执行上述代码,都会出现编译错误。错误在于拷贝构造函数。执行“A b = a”语句时,调用一次拷贝构造函数,因为拷贝构造函数采用“值传递”的方式,需要将a的值赋给other,因此需要再调用一次拷贝构造函数。而在新的一次调用中,又需将实参传递给形参……拷贝构造函数的无穷调用,最终会导致 stackoverflow
2.对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。
const修饰成员函数
有以下几点规则:
- const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数。
- const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的。
- const成员函数可以访问数据成员,不可以修改对象的数据,不管对象是否具有const性质。它在编译时,以是否修改成员数据为依据,进行检查。
- 然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的。
1 | class Circle{ |
最后举阿里巴巴一道笔试题作例子:
在gcc编译器下,针对以下代码:
1 | const char str1[] = "abc"; |
那么针对printf(“%d %d %d %d\n”, str1, str2, p1, p2)的结果,下列说法正确的是:
A. 输出的前两个数不同,输出的后两个数相同
B. 输出的前两个数相同,输出的后两个数相同。
C. 输出的前两个不同,输出的后两个数不同。
D. 输出的前两个数不同,输出的后两个数不同。
E. 4个数都相同。
F. 4个数都不同。
正确答案为A。
因为前两个定义的数组,存储在堆栈上,因此地址不同。而后两个指针指向常量,对于同一常量,在静态存储区仅有一份拷贝,因此后两个指针地址相同。