第1讲:const用法总结
几句话总结const
的用法。
1. const
常量与 #define
宏定义的区别?
- const 是一种“修饰符”,定义时必须初始化。
- 安全检查。const 变量需要经过编译器的规则检查。
- 节约空间。const 只有一份,
#define
有若干个拷贝。
2. const 作为局部变量
- const 对象默认为文件局部变量;
- const 对象需要在初始化时指明 extern 关键字,才能跨文件使用。
- 普通变量仅需在外部文件使用时,声明 extern 即可。
// 普通变量的配套使用
int ext;
extern int ext;
// const 变量的配套使用
extern const int ext = 12;
extern const int ext;
3. const 和指针
3.1 指向const的指针 const char *ptr
- 不能通过指针来改变对象的值
- 指针本身不是常量,所以定义时可以不用初始化(但秉持着所有定义都要初始化的原则,最基本也要初始化为空)
- 指向const的指针可以指向普通对象!
&int
可以初始化const int *
;
- 普通指针不能指向const对象!
const int
的地址不可以赋给int *
。这点解释了为什么const成员函数不能调用普通成员函数!从逻辑上即可解释:int*
在设计时就可以修改指向对象,所以让它指向const和设计初衷矛盾!
const int *
如有需要应转换为const void *
,而非普通的void *
;
3.2 const指针char * const ptr
- 本质上仍是一个const,所以必须进行初始化;而且之后不能修改,即不能指向其他对象;
- 如果指向的是普通类型,自然可以更改其指向对象的值
- (非const对象的)this指针就是该类型
3.3 指向const的const指针
- 必须初始化、之后不能修改指针的指向;
- (const对象的)this指针是该类型
4. const和函数参数
- 值传递时写 const 没有意义。因为是函数内是实参的副本,本体不受影响。
- 建议使用:指向const的指针、const引用。优势:
- 提升传递效率
- 确保本体的内容不被函数内部改变,即使本体是普通类型,其地址也能被 “指向常量的指针” 接受。
5. const 和类
class Apple{
public:
Apple(int i) : apple_number(i) {}
const int apple_number;
int add(int num) const;
int take();
private:
int people[100];
};
5.1 const成员
const成员只能先声明,后初始化!原因:只有创建了类的对象,才能容纳常量,这个顺序不能反。
一般可以采用的初始化方法为:
- 在构造函数的“初始化列表”中进行初始化。只能位于初始化列表,不能在构造函数体内初始化!
- 直接在外层初始化:
const int Apple::apple_number = 10;
5.2 const成员函数
在函数参数列表后面加上const
关键字。this指针从“const指针”,更进一步成为指向const的const指针,即 const Apple * const
。带来的影响是:
(1)const成员函数不能修改任何数据成员。
以const成员函数中使用成员变量
int x
为例,其完全调用形式是:this->x = (*this).x
。此时*this
的结果是const Apple
,即便x
只是个普通类型,却也被加上了const属性,导致不能被修改。
(2)const成员函数只能调用其他const成员函数,没法调用普通成员函数。
原因:const成员函数的this指针,在调用时传递给普通成员函数会报错!
const Apple * const
是没法初始化Apple * const
的!
(3)只有const成员函数才能操作const成员或const对象!
普通的
this
指针没法指向常量,只能指向普通对象。
(4)const对象只能调用const成员函数;普通对象两种函数都可以调用
const对象的地址可以初始化普通指针,没有
this
指针不兼容的问题。
(5)如果成员函数不修改数据(比如只返回值),从设计安全性角度来说,它应该被设计为const成员函数。
(6)常成员函数的另一个好处是能被常量对象和普通对象调用。