如何编写getter方法以便返回rvalue

时间:2013-12-04 10:46:42

标签: c++ visual-studio-2010

如果我们有这个类定义

class BusDetails
{
private:
    string m_busName;
public:
    string BusName() const { return m_busName; }
};

如何更改或使用getter方法,以便将返回值用作左值会产生编译错误?

例如,如果我像

一样使用它
int main(void)
{
    BusDetails bus;

    bus.BusName() = "abc";    // <--- This should give a compiler error
    cout << bus.BusName() << endl;

    return 0;
}

我没有编译错误,所以显然分配工作正常,但结果并不像预期的那样。

更新:这种行为与内置类型一样正常(例如,如果我将int作为返回类型而不是编译器在上面的代码行中出错string)。

4 个答案:

答案 0 :(得分:2)

BusName()被声明为const函数。所以它不能改变成员。 你的函数应该返回string&而不是const。

string& BusName() { return m_busName; }

另外你可以添加const对象(this是const):

const string& BusName() const { return m_busName; }

答案 1 :(得分:2)

目前尚不清楚你想要的行为。

  • 如果您希望分配是一个错误,并保留所有 值返回的灵活性(例如,您可以将代码修改为 返回计算值),您可以返回std::string const。 (这会抑制移动语义,但通常不会 一个大问题。)

  • 如果您希望能够修改“成员”,但仍然想要 保持关于如何实施的灵活性 该类,那么你应该提供一个setter方法。一 约定(不是唯一的)是提供一个getter函数 就像你现在一样(但返回std::string const),和 提供具有相同名称void BusName( std::string const& newValue )的函数来设置值。 (其他约定将使用SetBusName之类的名称,或返回 旧值,因此客户端代码可以保存和恢复它,或 返回*this,因此客户端代码可以链接操作: obj.BusName( "toto" ).SomethingElse( /*...*/ )

  • 您还可以提供一个返回引用的非const成员 到一个非常数。但是,如果你这样做,你也可以做 数据成员公开。

  • 最后,您可能会提供一个返回的非const成员 某种代理类,实际上分配给它 调用setter函数,并将其转换为std::string 打电话给吸气鬼。这是迄今为止最灵活的, if 你 想要支持客户的修改,但它也是 最复杂的,所以你可能不想使用它,除非你 需要。

答案 2 :(得分:1)

这就是你所写的预期行为。

您确实会返回m_busName的副本。因为你没有返回引用。因此,返回变量的临时副本,然后进行分配。 <{1}} operator=在该副本上被调用。

所以要走的路是"abc"。但这会给编译器错误。

你有点想要矛盾的事情。你说string& BusName() const { return m_busName; },但是你想要返回一个允许改变对象状态的引用。

但是,如果您不保证对象不会更改,您可以删除string BusName() const并使用

const

或者,如果您想保留string& BusName() { return m_busName; };

const

然而,这应该会给分配带来错误,当然。

功能也是如此。如果你通过引用传递参数,那么它就是一个引用。如果您看到您修改了副本,则必须未通过引用传递它,而是按值传递。

答案 3 :(得分:1)

该函数确实返回一个右值。

问题是std::string::operator= 的作品左边有一个右值。在C ++ 11之前,很难或不可能阻止它工作:在C ++ 11中,它们(相对较晚)添加了通常称为this的右值引用的内容:重载方法和in-的能力基于对象的右值状态的类运算符。

然而,std::string没有被修改,可能是没有太多时间和不喜欢破坏现有代码的混合物。

您可以通过几种方式解决此问题。您可以编写自己的字符串类,遵循对this的右值引用。您可以从std::string下降并专门阻止operator=。您可以编写一个具有std::string的访问者对象,该对象可以隐式地转换为std::string&&广告std::string&(基于this的rvalue状态),但阻止赋值{ {1}}方法。

这三个都有问题。最后一个是最少的问题,第二个是最隐蔽的陷阱,第一个只是苦差事。