大约 4 分钟
const变量
- 如果关键字const出现在星号左边,表示被指物是常量
- 如果出现在星号右边,表示指针自身是常量;
- 如果出现在星号两边,表示被指物和指针两者都是常量。
char greeting[] = "Hello";
char* p = greeting; // non-const pointer, non-const data
const char* P = greeting; // non-const pointer, const data
char* const p = greeting; // const pointer, non-const data
const char* const P = greeting; // const pointer, const data
如果被指物是常量,有些程序员会将关键字const写在类型之前,有些人会把它写在类型之后、星号之前。两种写法的意义相同,所以下列两个函数接受的参数类型是一样的:
void f1 (const Widget* pw); // E1获得一个指针,指向一个常量的(不变的)Widget对象.
void f2 (Widget const * pw); // f2 也是
const与函数声明式(函数返回值、各参数、函数自身(如果是成员函数))
在一个函数声明式内,const可以和这些产生关联:
- 函数返回值
- 各参数
- 函数自身(如果是成员函数)
函数返回值与参数
令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。
class Rational { ... };
const Rational operator* (const Rational& lhs, const Rational& rhs):
Rational a,b,c;
(a*b)=c; // 在a*b的成果上调用operator=
// 不加const会导致非报错的错误
const成员函数
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员**(准确地说是非静态数据成员)**作任何改变
真实程序中const对参大多用于 passed by pointer-to-const 或 passed by reference-to-const 的传递结果
两个流行概念
- bitwise constness
- 概念:成员函数只有在不吊改对象之任何成员变量(static除外)时才可以说是const。也就是说它不更改对县内的任何-个bit。
- 优点:容易侦测违反点,也是C+对常量性(constness)的定义
- 缺点:是许多成员函数蛛然不十足具备const性质却能通过bitwise测试,例如一个更改了“指针所指物“的成员函数虽然不能算是const
- logical constness
- 概念:一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。
- 举例:例如你的cTextBlockclass有可能高速缓存Ccache 文本区块的长度以便应付询问 length的实现当然不是bitwise const。 如果编译器用的是bitwise constness怎么办?答:使用mutable(可变的)释放掉non-static成员变量的bitwiseconstness约柬:
在const和non-const成员函数中避免重复
对于“bitwise-constness非我所欲“的问题,mutable是个解决办法,但它不能解决所有的const相关难题
class TextBlock {
public:
const char& cperator[] (std::sizet position) const
{
// 边 界 检 验 (bounds checking)
// 志 记 数 据 访 问 (log access data)
// 检 验 数 据 完 整 性 (verify data integrity)
return text [position];
}
char& operator(] (std::size_t position)
{
// 边 界 检 验 (bounds checking)
// 志 记 数 据 访 问 (log access data)
// 检 验 数 据 完 整 性 (verify data integrity)
return text [position];
}
Private:
std::string text;
}
例如这里会重复一些东西。这促使我们将常量性转除《easting away constuess》。
更安全的做法是:(如你所见,这份代码有两个转型动作,而不是一个)
class TextBlock {
public:
const char& operator[] (std::size_t position) const // 一 如 既 往
{
// 边 界 检 验 (bounds checking)
// 志 记 数 据 访 问 (log access data)
// 检 验 数 据 完 整 性 (verify data integrity)
return text[Position]
}
char& operator[] (std::size_t position) // 现 在 只 调 用 const op []
{
return const_cast<char&>( // 将 op [] 返 回 值 的 const 转 除
static_ cast<const TextBlock&>(*this)[position] // 为 *this 加 上 const,并调用 const op[]
);
}
...
};
总结
请记住:
- 将某些东西声明为const可帮助编译器侦测出错误用法。 const可被施加于
- 任何作用域内的对象
- 函数参数
- 函数返回类型
- 成员函数本体
- 编译器强制实施bitwise constness,但你编写程序时应该使用 “概念上的常量性“ (conceptual constness)。
- 当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。