const
是关于程序语义而不是关于实现细节。当成员函数const
不改变对象的可见状态时,您应该标记它,并且应该可以在本身的对象上调用const
。在const
类的成员函数中X
,类型this
为X const *
:指向常量X
对象的指针。因此,所有成员变量都有效地const
在该成员函数内(除了mutable
那些)。如果你有一个const
对象,你只能调用const
它的成员函数。
您可以使用mutable
指示成员变量即使在const
成员函数内也可能发生变化。这通常用于识别用于缓存结果的变量,或者用于不影响实际可观察状态的变量,例如互斥体(您仍然需要在const
成员函数中锁定互斥体)或使用计数器。
class X
{
int data;
mutable boost::mutex m;
public:
void set_data(int i)
{
boost::lock_guard<boost::mutex> lk(m);
data=i;
}
int get_data() const // we want to be able to get the data on a const object
{
boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
return data;
}
};
如果您通过指针而不是直接保存数据(包括智能指针,例如std::auto_ptr
or boost::shared_ptr
),则指针变为const
成员const
函数,而不是指向的数据,因此您可以修改指向的数据。
至于缓存:通常编译器不能这样做,因为状态可能会在调用之间发生变化(尤其是在我使用互斥锁的多线程示例中)。但是,如果定义是内联的,那么编译器可以将代码拉入调用函数并优化它在那里可以看到的内容。这可能会导致该函数实际上只被调用一次。
下一版本的C++ 标准 (C++0x)将有一个新的关键字constexpr
. 标记的函数constexpr
返回一个常量值,因此可以缓存结果。在这样的函数中可以做的事情是有限制的(以便编译器可以验证这个事实)。