C++常量成员函数返回类成员的引用

5
如果我有一个类成员函数:
bar* foo::get_value() const
{
  return &_value;
}

编译器会报错

无法使用类型为const bar *的rvalue初始化bar *类型的变量

在该类中,_value不是const

如果我有以下函数:

bar* foo::get_value() const
{
  return const_cast<bar *>(&_value);
}

它完全正常。

我认为声明成员函数为常量意味着承诺不修改类的内部内容,但是在const成员函数中,操作符&似乎返回一个常量指针。这是为什么?


1
你不能修改类的内部内容,因为它在const方法中是常量。 - BЈовић
4个回答

10
当您声明一个带有const关键字的函数时,您正在表明这是一个允许在非const和const对象实例上调用的函数。因为它可以在const实例上调用,所以该函数不应该改变对象。当您返回对内部对象的非const引用时,您提供了一种间接地改变对象内部状态的方式。为了解决此问题,请返回一个常量对象。
换句话说,不要写成:
Bar* Foo::GetBar() const

Do:

const Bar* Foo::GetBar() const

或者更好的是:
const Bar& Foo::GetBar() const

正如你所观察到的那样,const_cast 允许你破坏对象的常量性。一般情况下,应避免使用 const_cast;使用它是一种代码异味,会破坏既定的 const 保证。

3
当一个对象实例被声明为const时,它被视为其所有成员变量也是const,即除了已被声明为mutable关键字的成员变量。
因此,理论上,您可以将_value声明为mutable,这至少比使用const_cast<>更好。但它仍然不理想。正确的方法是提供两个重载函数。
const bar* foo::get_value() const
{
    return _value;
}

bar* foo::get_value()
{
    return _value;
}

(最好使用引用或智能指针而不是裸指针。)

1
问题在于 getter 函数的返回类型。你返回了 bar* 而不是 const bar*。前者允许调用 get_value 函数的代码修改对象,但是你的声明中明确禁止这样做,因为 _value 被声明为 const
你可以使用 const_cast 绕过这个问题,但这是不正确的。这就像告诉编译器“相信我,我知道我在做什么”,但在这种情况下,你并不知道。你无法控制调用代码对对象的操作。如果他们尝试修改它,那么就会产生未定义的行为。
让自己的生活更简单,只需让 getter 返回 const bar* 即可。
const bar* foo::get_value() const
{
  return &_value;
}

请注意,编译器错误消息基本上告诉您需要对代码进行的更改。

1

const成员函数仅适用于const对象。对于const对象,您无法更改其成员变量。这就是为什么编译器不允许您创建指向const对象的成员变量的非const指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接