C++中运算符重载的返回值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2337213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:06:27  来源:igfitidea点击:

return value of operator overloading in C++

c++operator-overloading

提问by skydoor

I have a question about the return value of operator overloading in C++. Generally, I found two cases, one is return-by-value, and one is return-by-reference. So what's the underneath rule of that? Especially at the case when you can use the operator continuously, such as cout<<x<<y.

我有一个关于 C++ 中运算符重载的返回值的问题。一般我发现有两种情况,一种是按值返回,一种是按引用返回。那么它的底层规则是什么?特别是在您可以连续使用运算符的情况下,例如cout<<x<<y

For example, when implementing a + operation "string + (string)". how would you return the return value, by ref or by val.

例如,在执行 + 操作时“字符串 +(字符串)”。您将如何通过 ref 或 val 返回返回值。

回答by Tyler McHenry

Some operators return by value, some by reference. In general, an operator whose result is a new value (such as +, -, etc) must return the new value by value, and an operator whose result is an existing value, but modified (such as <<, >>, +=, -=, etc), should return a reference to the modified value.

有些运算符按值返回,有些按引用返回。一般而言,结果为新值(如+、-等)的运算符必须逐值返回新值,而结果为现有值但已修改的运算符(如<<、>>、+ =、-= 等),应该返回对修改值的引用。

For example, coutis a std::ostream, and inserting data into the stream is a modifying operation, so to implement the <<operator to insert into an ostream, the operator is defined like this:

例如cout是 a std::ostream,向流中插入数据是一个修改操作,所以为了实现<<插入到 anostream的操作符,操作符定义如下:

std::ostream& operator<< (std::ostream& lhs, const MyType& rhs)
{
  // Do whatever to put the contents of the rhs object into the lhs stream
  return lhs;
}

This way, when you have a compound statement like cout << x << y, the sub-expression cout << xis evaluated first, and then the expression [result of cout << x ] << yis evaluated. Since the operator <<on xreturns a reference to cout, the expression [result of cout << x ] << yis equivalent to cout << y, as expected.

这样,当您有像 一样的复合语句时cout << x << ycout << x会先计算子表达式,然后再计算表达式[result of cout << x ] << y。由于运算符<<onx返回对 的引用cout,因此表达式[result of cout << x ] << y等效于cout << y,正如预期的那样。

Conversely, for "string + string", the result is a new string (both original strings are unchanged), so it must return by value (otherwise you would be returning a reference to a temporary, which is undefined behavior).

相反,对于“字符串 + 字符串”,结果是一个新字符串(两个原始字符串都没有改变),因此它必须按值返回(否则您将返回对临时对象的引用,这是未定义的行为)。

回答by skydoor

To attempt an answer to your question regarding strings, the operator+() for strings is almost always implemented as a free (non-member) function so that implicit conversions can be performed on either parameter. That is so you can say things like:

要尝试回答有关字符串的问题,字符串的 operator+() 几乎总是作为自由(非成员)函数实现,以便可以对任一参数执行隐式转换。这样你就可以这样说:

string s1 = "bar";
string s2 = "foo" + s1;

Given that, and that we can see that neither parameter can be changed, it must be declared as:

鉴于此,并且我们可以看到两个参数都不能更改,因此必须将其声明为:

RETURN_TYPE operator +( const string & a, const string & b );

We ignore the RETURN_TYPE for the moment. As we cannot return either parameter (because we can't change them), the implementation must create a new, concatenated value:

我们暂时忽略 RETURN_TYPE。因为我们不能返回任何一个参数(因为我们不能改变它们),实现必须创建一个新的、连接的值:

RETURN_TYPE operator +( const string & a, const string & b ) {
    string newval = a;
    newval += b;    // a common implementation
    return newval;
}

Now if we make RETURN_TYPE a reference, we will be returning a reference to a local object, which is a well-known no-no as the local object don't exist outside the function. So our only choice is to return a value, i.e. a copy:

现在,如果我们将 RETURN_TYPE 设为引用,我们将返回对本地对象的引用,这是众所周知的禁忌,因为本地对象不存在于函数之外。所以我们唯一的选择是返回一个值,即一个副本:

string operator +( const string & a, const string & b ) {
    string newval = a;
    newval += b;    // a common implementation
    return newval;
}

回答by Michael Burr

If you want your operator overload to behave like the built-in operator, then the rule is pretty simple; the standard defines exactly how the built-in operators behave and will indicate if the result of a built-in is an rvalueor an lvalue.

如果您希望运算符重载的行为类似于内置运算符,那么规则非常简单;该标准准确定义了内置运算符的行为方式,并将指示内置运算符的结果是 anrvalue还是 an lvalue

The rule you should use is:

您应该使用的规则是:

  • if the built-in operator returns an rvaluethen your overload should return a reference
  • if the built-in returns an lvaluethen your overload should return a value
  • 如果内置运算符返回 anrvalue那么你的重载应该返回一个引用
  • 如果内置返回 anlvalue那么你的重载应该返回一个值

However, your overload isn't required to return the same kind of result as the built-in, though that's what you should do unless you have a good reason to do otherwise.

但是,您的重载不需要返回与内置函数相同的结果,尽管这是您应该做的,除非您有充分的理由不这样做。

For example, KennyTM noted in a comment to another answer that the stream overloads for the <<and >>operators return a reference to the left operand, which is not how the built-ins work. But the designers of the stream interface did this so stream I/O could be chained.

例如,KennyTM 在对另一个答案的评论中指出,<<and>>运算符的流重载返回对左操作数的引用,这不是内置函数的工作方式。但是流接口的设计者这样做是为了可以链接流 I/O。

回答by Brian R. Bondy

Depending on the operator you may have to return by value.

根据运算符,您可能必须按值返回。

When both can be used though, like in operator+= you could consider the following:

当两者都可以使用时,就像在 operator+= 中一样,您可以考虑以下内容:

  • If your objects are immutable it's probably better to return by value.
  • If your objects are mutable it's probably better to return by reference.
  • 如果您的对象是不可变的,那么按值返回可能更好。
  • 如果您的对象是可变的,最好通过引用返回。

回答by thebretness

Usually you return by reference in an operation that changes the value of the things it's operating on, like =or +=. All other operations are return by value.

通常你在一个操作中通过引用返回,它改变了它正在操作的东西的值,比如=+=。所有其他操作都是按值返回。

This is more a rule of thumb, though. You can design your operator either way.

不过,这更像是一条经验法则。您可以以任何一种方式设计您的运算符。