我知道不允许该函数更改对象的状态,但是我想我读过某个地方,允许编译器假定,如果使用相同的参数调用该函数,它将返回相同的值,并且因此可以重用缓存的值(如果可用)。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class object
{
int get_value(int n) const
{
...
}
...
object x;
int a = x.get_value(1);
...
int b = x.get_value(1); |
,那么编译器可以优化第二次调用,并使用寄存器中的值或简单地执行b = a;
这是真的吗?
const与程序语义有关,与实现细节无关。当成员函数const不会更改对象的可见状态时,应对其进行标记,并且应该可以在本身为const的对象上对其进行调用。在类X的const成员函数中,this的类型为X const *:指向常量X对象的指针。因此,所有成员变量实际上都是该成员函数中的const(mutable除外)。如果有const对象,则只能在其上调用const成员函数。
可以使用mutable表示成员变量甚至在const成员函数中也可能发生变化。通常用于标识用于缓存结果的变量或不影响实际可观察??状态的变量,例如互斥锁(您仍然需要将互斥锁锁定在const成员函数中)或使用计数器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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成员函数中变为const,但不是指向对于数据,您可以修改指向的数据。
对于缓存:通常,编译器无法执行此操作,因为状态可能在两次调用之间改变(尤其是在我使用互斥锁的多线程示例中)。但是,如果定义是内联的,则编译器可以将代码提取到调用函数中,并优化在该函数中可以看到的内容。这可能导致该函数仅被有效调用一次。
下一个版本的C标准(C 0x)将具有新的关键字constexpr。标记为constexpr的函数返回常数,因此可以将结果缓存。在此函数中可以执行的操作受到限制(以便编译器可以验证此事实)。
在成员变量上可变的关键字允许const函数更改当前对象的状态。
而且不,它不缓存数据(至少不是所有调用),因为以下代码是随时间变化的有效const函数:
1
| int something() const { return m_pSomeObject->NextValue(); } |
请注意,指针可以是const,尽管所指向的对象不是const,因此对SomeObject的NextValue的调用可能会或可能不会更改其自身的内部状态。这会使函数每次调用时都返回不同的值。
但是,我无法回答编译器如何使用const方法。我听说它可以优化某些功能,尽管我必须对其进行
不。
const方法是一种不会更改对象状态(即其字段)的方法,但是您不能假设给定相同的输入,就可以确定const方法的返回值。换句话说,const关键字并不意味着该功能是一对一的。例如,返回当前时间的方法是const方法,但是其返回值在两次调用之间改变。
在这种情况下,const成员函数意味着this也被视为const指针。实际上,这意味着您不允许在const成员函数内修改this的状态。
对于无副作用的函数(例如,您尝试的是要实现),GCC具有一个名为pure的\\"功能属性\\\\"(您可以通过说__attribute__((pure))来使用它):http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes。 html
成员函数上的const关键字将此参数标记为常量。该函数仍然可以静音全局数据(因此不能被缓存),但是不能静音对象数据(允许调用const对象)。
还允许使用
const方法修改静态本地。例如,以下代码是完全合法的(重复调用bar()将返回递增值-而不是缓存的0):
1 2 3 4 5 6 7 8 9
| class Foo
{
public:
int bar() const
{
static int x = 0;
return x++;
}
}; |
Corey是正确的,但请记住,任何标记为可变的成员变量都可以在const成员函数中进行修改。
这也意味着可以从其他const函数或通过调用这些函数其他const引用。
编辑:该死,被9秒殴打...。9! :)
除了成员函数可以修改全局数据这一事实之外,成员函数还可以修改相关对象的显式声明的可变成员。
我对此表示怀疑,该函数是否仍可以调用一个全局函数,该函数可以更改世界的状态并且不违反const。