我知道该函数不允许更改对象的状态,但我想我在某处读过允许编译器假设如果使用相同的参数调用函数,它将返回相同的值并且因此,如果可用,则可以重用缓存的值。 e.g。
class object
{
int get_value(int n) const
{
...
}
...
object x;
int a = x.get_value(1);
...
int b = x.get_value(1);
然后编译器可以优化第二个调用,并使用寄存器中的值或只执行b = a;
这是真的吗?
答案 0 :(得分:24)
const
是关于程序语义而不是实现细节。如果成员函数const
没有更改对象的可见状态,则应标记该成员函数,并且应该在对象const
上可调用。在类const
的{{1}}成员函数中,X
的类型为this
:指向常量X const *
对象的指针。因此,所有成员变量在该成员函数中有效X
(const
除外)。如果您有mutable
个对象,则只能在其上调用const
个成员函数。
您可以使用const
表示即使在mutable
成员函数中成员变量也可能发生变化。这通常用于标识用于缓存结果的变量,或用于不影响实际可观察状态的变量(如互斥锁(您仍需要锁定const
成员函数中的互斥锁)或使用计数器。) / p>
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
等智能指针)保存数据,则指针在boost::shared_ptr
成员函数中变为const
,但不是指向的数据,因此您可以修改指向的数据。
至于缓存:通常编译器不能这样做,因为状态可能在调用之间发生变化(特别是在我的多线程示例中使用互斥锁)。但是,如果定义是内联的,那么编译器可以将代码拉入调用函数并优化其可以看到的内容。这可能导致函数有效仅被调用一次。
C++ Standard (C++0x)的下一个版本将有一个新关键字const
。标记为constexpr
的函数返回一个常量值,因此可以缓存结果。在这样的函数中你可以做什么是有限的(为了编译器可以验证这个事实)。
答案 1 :(得分:3)
没有。
const方法是一种不改变对象状态(即其字段)的方法,但是你不能假设给定相同的输入,确定const方法的返回值。换句话说,const
关键字并不意味着该函数是一对一的。例如,返回当前时间的方法是const方法,但其返回值在调用之间发生变化。
答案 2 :(得分:3)
成员变量上的关键字mutable允许const函数改变手头对象的状态。
不,它不会缓存数据(至少不是所有调用),因为以下代码是一个随时间变化的有效const函数:
int something() const { return m_pSomeObject->NextValue(); }
请注意,指针可以是const,虽然指向的对象不是const,因此在SomeObject上调用NextValue可能会也可能不会改变它自己的内部状态。这会导致函数在每次调用时返回不同的值。
但是,我无法回答编译器如何使用const方法。我听说它可以优化某些事情,但我必须要确定它。
答案 3 :(得分:2)
成员函数上的const关键字将 this 参数标记为常量。该函数仍然可以使全局数据静音(因此无法缓存),而不是对象数据(允许对const对象进行调用)。
答案 4 :(得分:2)
在此上下文中,const
成员函数意味着this
也被视为const
指针。实际上,这意味着您不能修改this
成员函数中const
的状态。
对于无副作用函数(即你想要实现的目标),GCC有一个名为pure
的“函数属性”(通过说__attribute__((pure))
来使用它):{{ 3}}
答案 5 :(得分:0)
我对此表示怀疑,该函数仍然可以调用一个改变世界状态而不是违反const的全局函数。
答案 6 :(得分:0)
除了成员函数可以修改全局数据这一事实之外,成员函数还可以修改相关对象的显式声明的可变成员。
答案 7 :(得分:0)
Corey是正确的,但请记住,在const成员函数中可以修改标记为 mutable 的所有成员变量。
这也意味着可以从其他const函数或其他const引用中调用这些函数。
编辑:该死的,被殴打了9秒...... 9! :)
答案 8 :(得分:0)
const方法也允许修改静态本地。例如,以下内容是完全合法的(对bar()的重复调用将返回增加的值 - 而不是缓存的0):
class Foo
{
public:
int bar() const
{
static int x = 0;
return x++;
}
};