const成员函数的语义是什么?

时间:2008-09-19 01:38:28

标签: c++ methods const

我知道该函数不允许更改对象的状态,但我想我在某处读过允许编译器假设如果使用相同的参数调用函数,它将返回相同的值并且因此,如果可用,则可以重用缓存的值。 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;

这是真的吗?

9 个答案:

答案 0 :(得分:24)

const是关于程序语义而不是实现细节。如果成员函数const没有更改对象的可见状态,则应标记该成员函数,并且应该在对象const上可调用。在类const的{​​{1}}成员函数中,X的类型为this:指向常量X const *对象的指针。因此,所有成员变量在该成员函数中有效Xconst除外)。如果您有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++;
    }
};