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

发布于 2024-08-23 04:10:46 字数 197 浏览 5 评论 0 原文

我对 C++ 中运算符重载的返回值有疑问。一般来说,我发现了两种情况,一种是按值返回,一种是按引用返回。那么这背后的规则是什么呢?特别是在可以连续使用运算符的情况下,例如cout<

例如,当实现+操作“string + (string)”时。如何通过 ref 或 val 返回返回值。

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

后知后觉 2024-08-30 04:10:46

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

例如,cout是一个std::ostream,向流中插入数据是一个修改操作,所以要实现<< > 运算符插入到 ostream 中,该运算符的定义如下:

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;
}

这样,当您有像 cout << 这样的复合语句时, 该运算符的定义如下: x << y,子表达式cout <<首先计算 x,然后计算表达式 [result of cout <<; x ] << y 被评估。由于 x 上的运算符 << 返回对 cout 的引用,因此表达式 [result of cout << x ] << y 等价于 cout << y,正如预期的那样。

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

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, cout is 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:

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 << x is evaluated first, and then the expression [result of cout << x ] << y is evaluated. Since the operator << on x returns a reference to cout, the expression [result of cout << x ] << y is equivalent to cout << y, as expected.

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).

清君侧 2024-08-30 04:10:46

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

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

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

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

我们暂时忽略 RETURN_TYPE。由于我们无法返回任何一个参数(因为我们无法更改它们),因此实现必须创建一个新的串联值:

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

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

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

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:

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 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:

string operator +( const string & a, const string & b ) {
    string newval = a;
    newval += b;    // a common implementation
    return newval;
}
合久必婚 2024-08-30 04:10:46

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

您应该使用的规则是:

  • 如果内置运算符返回一个rvalue,那么您的重载应该返回一个引用;
  • 如果内置运算符返回一个lvalue,那么您的重载应该返回a value

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

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

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 rvalue or an lvalue.

The rule you should use is:

  • if the built-in operator returns an rvalue then your overload should return a reference
  • if the built-in returns an lvalue then your overload should return a value

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.

空袭的梦i 2024-08-30 04:10:46

根据运营商的不同,您可能必须按值返回。

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

  • 如果您的对象是不可变的,那么最好按值返回。
  • 如果您的对象是可变的,那么最好通过引用返回。

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:

  • 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.
后eg是否自 2024-08-30 04:10:46

通常,您在更改其所操作对象的值的操作中按引用返回,例如 =+=。所有其他操作均按值返回。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文