const与指针及函数
cppreference-zh-201806 中的简单定义
const 对象——类型为 const-qualified 的对象,或 const 对象的非 mutable 子对象。这种对象不能修改:尝试直接这么做是编译时错误,且尝试间接这么做(例如通过到非 const 类型的引用或指针修改 const 对象)导致未定义行为。
const与指针
声明指针时,在类型前或后都可以使用关键字const
,也可在两个位置都使用。例如,下面都是合法的声明,但是含义大不同:1
2
3const int * pOne; //指向整形常量 的指针,它指向的值不能修改
int * const pTwo; //指向整形的常量指针 ,它不能在指向别的变量,但指向(变量)的值可以修改。
const int *const pThree; //指向整形常量 的常量指针 。它既不能再指向别的常量,指向的值也不能修改。
const与函数
《代码大全》说:代码是写给人看到的,我觉得const的设计就出于这个目的。即,通过避免人为的失误来提升程序的健壮性。从这个角度出发,很多设计的合理性就显而易见了。
用const修饰函数的参数
应用背景
我们经常会将自定义类型作为函数参数。如果使用值传递,则会产生临时对象。临时对象的构造、复制、析构过程都将消耗资源。因此,我们会使用引用传递来避免这个开销。引用传递意味着我们可以修改实参的值,我们有时候并不希望这件事发生,需要限制函数体对实参的修改的能力。
应用方法
在引用传递的基础上加上const关键词,即:const A &a
。这个语法中兼备了高效和安全。其中,&
保证了高效,const
缩小了权限,从而保证了安全。
错误的应用
void f(const int a)
值传递本身就意味着对形参的修改不会影响实参。写法并非错误,事实上在某些场合也具备意义。但是对于避免影响形参这个目的,是无意义的。void f(const int &a)
像int这样的内部类型作为函数参数被传递时,不存在构造、复制、析构的过程,复制的速度非常快。这种写法和void f(int a)
的效率几乎相当。写法并非错误,事实上在某些场合也具备意义。但是对于安全又高效地使用实参这个目的,是无意义的。用const修饰函数的返回值
申明格式为const A* GetA(void);
。和上一节同理,也是为了更安全地使用&。引用传递返回值一般出现在链式表达中,const则限制了不正常的链式表达。
程序举例:
1 | class A |
用const修饰成员函数
申明格式举例:int C::f(void) const;
。作用是:f函数不可以修改数据成员,或者调用其它非const成员函数。
程序举例:
1 | class Stack |
为什么const放在后面?因为const在修饰成员函数时,其实修饰的是*this
。而this没有显式地写出来,所以就放在后面了(个人理解)。
如果调用了非const成员函数,VS2017会报类似于这样的错误:
error C2662: “CDate::COMPARE CDate::comparef(CDate,const CDate &)”: 不能将“this”指针从“const CDate”转换为“CDate &”
注意:const不能修饰静态成员函数。而静态成员函数属于类而非对象,因此不可以被const修饰。