const多才多艺。可以修饰全局、局部变量,或修饰文件、函数或者区块作用域中被声明为static的对象。也可以用来修饰class内部的static和non-static成员变量。
const修饰指针对于指针,const可以修饰指针所指物,也可以修饰指针本身。
char greeting[] = "Hello"; char* p = greeting; // non-const pointer, non-const data const char* p1 = greeting; // non-const pointer, conda data char* const p2 = greeting; // const pointer, non-const data const char* const p3 = greeting; // const pointer, const data
记忆方法,当const出现在 * 左侧的时候,表示被指物是常量;当const出现在 * 右侧时,表示的是指针自身是常量。
const修饰函数- 修饰返回值
class Rational
{
private:
public:
Rational() {}
~Rational() {}
friend const Rational operator* (const Rational& lhs, const Rational& rhs);
};
虽然不建议返回const对象,但是有时会避免一种不经意间发生的错误。
Rational a, b, c;
if (a * b = c) { // error: passing 'const Rational' as 'this' argument discards qualifiers
// todo
}
- const成员函数
class Fred {
public:
void inspect() const; // This member promises NOT to change *this
void mutate(); // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
changeable.inspect(); // Okay: doesn't change a changeable object
changeable.mutate(); // Okay: changes a changeable object
unchangeable.inspect(); // Okay: doesn't change an unchangeable object
unchangeable.mutate(); // ERROR: attempt to change unchangeable object
}
- const-overloading
class Fred { };
class MyFredList {
public:
const Fred& operator[] (unsigned index) const; // Subscript operators often come in pairs
Fred& operator[] (unsigned index); // Subscript operators often come in pairs
// ...
};
很多人忽视了一个C++的重要特性:两个成员函数如果只是常量性(constness)不同,可以被重载。
通常下标运算符重载成对出现。
```cpp
void f(MyFredList& a) // The MyFredList is non-const
{
// Okay to call methods that inspect (look but not mutate/change) the Fred at a[3]:
Fred x = a[3]; // Doesn't change to the Fred at a[3]: merely makes a copy of that Fred
a[3].inspect(); // Doesn't change to the Fred at a[3]: inspect() const is an inspector-method
// Okay to call methods that DO change the Fred at a[3]:
Fred y;
a[3] = y; // Changes the Fred at a[3]
a[3].mutate(); // Changes the Fred at a[3]: mutate() is a mutator-method
}
void f(const MyFredList& a) // The MyFredList is const
{
// Okay to call methods that DON'T change the Fred at a[3]:
Fred x = a[3];
a[3].inspect();
// Compile-time error (fortunately!) if you try to mutate/change the Fred at a[3]:
Fred y;
a[3] = y; // Fortunately(!) the compiler catches this error at compile-time
a[3].mutate(); // Fortunately(!) the compiler catches this error at compile-time
}
- 物理常量 vs 逻辑常量
物理常量(physical constness)也称为bitwise constness。物理常量的阵营认为,成员函数不更改对象内的任意一个bit。
而不幸的是,很多成员函数并不十足具备const的性质却能通过bitwise的测试。
比如如下代码,我们有一个类型为char*的成员变量,operator[]不更改pText,于是编译器开心地认为它是bitwise的。
但是,事实上通过以下代码,终究改变了其值。
class TextBlock
{
private:
char* pText;
mutable std::size_t textLength;
// std::size_t textLength;
mutable bool lengthIsValid;
// bool lengthIsValid;
public:
TextBlock() {}
~TextBlock() {}
std::size_t length() const;
char& operator[](std::size_t position) const { // bitwise声明,但是不适当。
return pText[position];
}
};
std::size_t TextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText);
lengthIsValid = true;
}
return textLength;
}
const TextBlock tb("abcd");
char* pc = & tb[0];
*pc = 'T';
Reference
- IOS CPP: Const Correctness



