1

运算符重载

表明这是通过以下方式完成的

class X {
  X& operator+=(const X& rhs)
  {
    // actual addition of rhs to *this
    return *this;
  }
};
inline X operator+(X lhs, const X& rhs)
{
  lhs += rhs;
  return lhs;
}

我明白为什么参数lhs需要按值取值,但为什么我们需要按值返回呢?我的意思是,以下问题有什么问题:

inline X& operator+(X lhs, const X& rhs)
{
  lhs += rhs;
  return lhs;
}

在函数内部,lhs是一个新的X,修改它不会影响两个操作数中的任何一个。由于这是新的,我们可以通过引用返回它,对吗?

4

3 回答 3

3

The problem of returning a reference to a local object is that the caller will receive something that is already dead on arrival.

When you exit from a function all locals are destroyed, so you cannot keep using references to them.

Code like

const X& res = a+b;

would works if the operator returns by value because there is a specific rule in the language that says that temporary objects bound to references will be kept alive until the reference itself is destroyed.

Returning a reference instead is different because the lifetime of the object is a responsibility of the called operator, not of the caller. So the end result will be a reference that is bound to an object that has already been destroyed.

Even just

X res;
res = a+b;

would not work, because when the operator call returns the object is destroyed before the assignment is made to res. Same would be in case of a copy constructor X res = a+b;.

于 2013-05-28T06:36:59.023 回答
0

Never return ba reference if the value you are referencing will cease to exist after exiting the function.

In this case, lhs will exist until the function returns. If you return by reference, that reference will "point" to a value that is no more, and any attempt to use it will result in undefined behavior.

That's the reason for return by value. But no worries, many compilers can optimize the additional copy away, and it is in fact no copy but a move operation, so even if it's not optimized away, "heavy" object will be moved and not copied since C++11.

于 2013-05-28T06:38:02.913 回答
0

不是严格回答问题,而是为了帮助理解引用......返回引用时要非常谨慎,除非您知道所指对象(被引用的对象)是稳定的。

这样做是不安全的

const std::string& doNothing(const std::string& x) {return x;}

您将在如下所示的第二次通话中陷入困境

std::string baa = "sheep";
std::cout << doNothing(baa) << std::endl;    // works
std::cout << doNothing("goat") << std::endl; // UNSAFE

这是因为第二次调用涉及隐式创建临时对象(使用构造函数调用的 std::string 类型string("goat")

相比之下,从name()

class Person
{
  private: std::string _name;
  public: const std::string& name() { return _name; }
  // other constructors and ways to set a _name
};

可以合理地确保类对象(以及它的 internal _name)将保留足够长的时间以使引用对调用者有用。

于 2017-02-12T04:06:48.593 回答