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

2021-12-23 00:00:00 methods constants c++

我知道该函数不允许更改对象的状态,但我想我在某处读到过编译器可以假设如果使用相同的参数调用该函数,它将返回相同的值并且因此可以重用缓存值(如果可用).例如

I understand that the function is not allowed to change the state of the object, but I thought I read somewhere that the compiler was allowed to assume that if the function was called with the same arguments, it would return the same value and thus could reuse a cached value if it was available. 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;

then the compiler could optimize the second call away and either use the value in a register or simply do b = a;

这是真的吗?

推荐答案

const 是关于程序语义的,而不是关于实现细节的.当成员函数不改变对象的可见状态时,你应该标记它const,并且应该可以在本身是const的对象上调用.在类 X 上的 const 成员函数中,this 的类型是 X const *:指向常量的指针X 对象.因此,所有成员变量在该成员函数中都是有效的const(mutable 除外).如果你有一个 const 对象,你只能在它上面调用 const 成员函数.

const is about program semantics and not about implementation details. You should mark a member function const when it does not change the visible state of the object, and should be callable on an object that is itself const. Within a const member function on a class X, the type of this is X const *: pointer to constant X object. Thus all member variables are effectively const within that member function (except mutable ones). If you have a const object, you can only call const member functions on it.

您可以使用 mutable 表示成员变量即使在 const 成员函数中也可能发生变化.这通常用于标识用于缓存结果的变量,或不影响实际可观察??状态的变量,例如互斥锁(您仍然需要在 const 成员函数中锁定互斥锁)或使用计数器.

You can use mutable to indicate that a member variable may change even within a const member function. This is typically used to identify variables used for caching results, or for variables that don't affect the actual observable state such as mutexes (you still need to lock the mutex in the const member functions) or use counters.

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_ptrboost::shared_ptr),则指针变为 const 成员函数中的 const,但不是指向的数据,因此可以修改指向的数据.

If you hold the data by pointer rather than directly (including smart pointers such as std::auto_ptr or boost::shared_ptr) then the pointer becomes const in a const member function, but not the pointed-to data, so you can modify the pointed-to data.

至于缓存:通常编译器不能这样做,因为状态可能会在调用之间发生变化(特别是在我的多线程示例中使用互斥锁).但是,如果定义是内联的,那么编译器可以将代码拉入调用函数并优化它在那里可以看到的内容.这可能会导致函数有效只被调用一次.

As for caching: in general the compiler cannot do this because the state might change between calls (especially in my multi-threaded example with the mutex). However, if the definition is inline then the compiler can pull the code into the calling function and optimize what it can see there. This might result in the function effectively only being called once.

C++ 标准 (C++0x) 的下一版本将有一个新关键字 constexpr.标记为 constexpr 的函数返回一个常量值,因此可以缓存结果.您可以在这样的函数中执行的操作是有限的(以便编译器可以验证这一事实).

The next version of the C++ Standard (C++0x) will have a new keyword constexpr. Functions tagged constexpr return a constant value, so the results can be cached. There are limits on what you can do in such a function (in order that the compiler can verify this fact).

相关文章