目录
[条款03:尽可能使用const(Use const whenever possible)](#条款03:尽可能使用const(Use const whenever possible))
[const修饰 指针](#const修饰 指针)
[const修饰 STL迭代器](#const修饰 STL迭代器)
[const 修饰 类成员](#const 修饰 类成员)
[const修饰 函数](#const修饰 函数)
条款03:尽可能使用const(Use const whenever possible)
const 概览
真实内含 :它允许你指定一个语义约束 (即指定某个对象"不该被改动" ),而编译器会强制实施这项约束。它不仅向编译器传达信息,也向其他程序员表明:该值在其生命周期内应保持不变 。只要"某值保持不变"确实符合事实 ,就应当明确写出 const,因为这能借助编译器的力量,在编译期防止意外修改(确保约束不被违反),从而提升程序的正确性与可维护性。
多才多艺:const的适用范围非常广泛,它可以:
- 修饰global或namespace作用域中的常量
- 修饰文件作用域、函数作用域或区块作用域中声明为static的对象
const 修饰 指针
可以指出指针自身、指针所指物 或 两者都是(或都不是)const
结论1:const出现在星号*
- 左边 :表示被指物 是常量(即指针**++指向的内容++**不能修改)
- 右边 :表示指针本身 是常量(即**++指针的指向++**不能修改)
- 两边 :表示被指物和指针 两者都是常量
结论2:两种写法的意义相同(等价)
- 写法1 :const写在**"类型之前"**
- 写法2 :const写在**"类型之后、星号之前"**
小结 :const修饰指针时,++只关心++ 其出现在星号*的左边还是右边,**++并不关心++**其出现在类型的左边还是右边。
const 修饰 STL 迭代器
在STL中,每个容器内部都会通过using或typedef定义2种类型的迭代器,即iterator和const_iterator。
- Container::iterator:T*
- Container::const_iterator:const T*(表示迭代器所指的东西不可被改动)
- const Container::iterator :T* const(表示迭代器不得指向不同的东西,但它所指的东西的值是可以改动的)
- const Container::const_iterator :const T* const
- 注1:STL迭代器是基于"指针"进行建模的,因此迭代器的作用类似于T*的指针。
- 注2:声明迭代器为const 就像 声明指针为const 一样。
const 修饰 类成员
non-static 成员:对象级别(每个对象拥有一份)
static 成员:类级别(所有对象共享一份)
const修饰 函数(参数、返回值、自身)
const 修饰 函数返回值 :防止客户对返回值进行无意义或错误的修改(详见"条款21"、"条款24")待补充
const 修饰 函数参数:详见"条款20"
- reference:避免参数的复制、构造和析构
- const:避免数据源被修改
const 修饰 函数自身(成员函数) :编译器强制实施bitwise constness,但编写程序时应该使用logical constness。(待补充)
- 注1:该函数不能修改对象状态(this指针的类型为const A* const)
- 注2:const为函数签名的一部分
const 修饰 函数自身(成员函数) :当const和non-const成员函数有着实质等价的实现时,令 non-const 版本 调用 const 版本 可以避免代码重复。
- 问题引入 :假设TextBlock中的operator[]不仅返回对适当字符的引用,还执行边界检查 (bounds checking) 、记录访问信息 (logged access info.) 、甚至可能进行数据完整性验证 (verify data integrity)。
- 实现1 (可行,不推荐) :将上述所有操作同时放进两个版本的 operator[] → 代码重复以及伴随的编译时间、维护、代码膨胀等问题
- 实现2 (可行,不推荐) :将上述所有操作移到另一个成员函数(通常为private),并令两个版本的operator[]调用它 → 代码重复(两次函数调用、两次return返回)
- 实现3 (可行,推荐) :令 non-const 版本 调用 const 版本 → 两次转型操作
- 分析(安全) :non-const 成员函数 可以对其对象做任何动作,因此在函数内部调用const成员函数并不会带来风险。另外,以static_cast作用于*this,并不存在const相关危险。
- 第一次转型 :static_cast <const TextBlock&> → 为 *this 添加 const修饰,使其从原始类型TextBlock& 转型为 const TextBlock&(即将non-const 对象 转为 const 对象),以便后续调用operator[]时得以调用const版本(否则会陷入无穷递归)
- 第二次转型 :const_cast <char&> → 从 const operator[]的返回值中 移除 const修饰(注意,去掉返回值上的const是安全的,因为non-const operator[]的调用者首先必须有一个non-const对象,否则就不能够调用non-const函数)
- 实现4 (不可行) :令 const 版本 调用 non-const 版本
- 分析(不安全) :首先,若想代码通过编译,必须通过const_cast去掉*this对象的const修饰,这便是一个明显的警讯(往往意味着设计上已经出现问题)。其次,const 成员函数 承诺绝不改变 其对象的逻辑状态,non-const 成员函数 却没有这般承诺。如果在const函数内调用non-const函数,会导致曾经承诺不改动的对象有可能因此被改动。




