为什么引用成员可以被const成员函数修改?

时间:2014-05-02 20:57:28

标签: c++

以下将compile即使const成员函数将修改成员的值。怎么样?

#include <iostream>

struct foo
{
    std::string &str;
    foo(std::string &other) : str(other) {}

    void operator()(std::string &some) const
    {
        str += some;
    }
};

int main()
{
    std::string ext("Hello");
    foo a{ ext };

    std::string more(" world!");
    a(more);

    cout << a.str;
    return 0;
}

2 个答案:

答案 0 :(得分:11)

将引用视为经典指针:

#include <iostream>

struct foo
{
    std::string * const str; // is the same as std::string &str
    foo(std::string &other) : str(&other) {}

    void operator()(std::string &some) const
    {
        *str += some;
    }
};

int main()
{
    std::string ext("Hello");
    foo a{ ext };

    std::string more(" world!");
    a(more);

    cout << a.str;
    return 0;
}

您将看到指针不会改变,只会指向它指向的值。

答案 1 :(得分:1)

类成员函数的const限定符表示此成员函数(例如foo::operator() const)无法从客户端的角度更改对象的状态< / em>(即它的抽象状态)。这与说对象的原始位不会改变不完全相同。

C ++编译器暂时将对象视为原始位,除非它们可以解析the problem of aliasing。在你的情况下,编译器不能。这是因为存在非常数别名(即std::string &str),因此对象的状态是可修改的。

也就是说,在对象operator()上调用a不会更改a的状态(即,虽然ext已更改,但str仍然存在别名为ext)。

上面还解释了为什么用指向常量的指针(即std::string * const str)指向一个对象并不能保证对象不会被修改。它只能保证对象不会通过该指针进行更改。