跳至主要內容

LincZero大约 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-constpassed 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可被施加于
    1. 任何作用域内的对象
    2. 函数参数
    3. 函数返回类型
    4. 成员函数本体
  • 编译器强制实施bitwise constness,但你编写程序时应该使用 “概念上的常量性“ (conceptual constness)。
  • 当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复