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

我有一个关于在C ++中重载操作符的返回值的问题。 一般来说,我发现了两种情况,一种是价值回报,一种是参考回报。 那么下面的规则是什么? 特别是在可连续使用操作员的情况下,如cout<<x<<y

例如,当执行+操作“string +(string)”时。 你将如何通过ref或val返回返回值。

一些运营商通过价值回报,一些通过参考。 一般来说,一个结果是一个新值(如+, – 等)的运算符必须按值返回新的值,而运算符的结果是一个现有的值,但被修改(如<<,>>,+ =, – =等),应该返回修改后的值的引用。

例如, cout是一个std::ostream ,向数据stream中插入数据是一个修改操作,所以为了实现<<操作符插入到一个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这样的复合语句时,首先计算子expression式cout << x ,然后计算expression式[result of cout << x ] << y 。 由于运算符<< on x返回对cout的引用,所以[result of cout << x ] << y相当。

相反,对于“string+string”,结果是一个新的string(两个原始string都不变),所以它必须返回值(否则你会返回一个临时的引用,这是未定义的行为)。

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

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

既然如此,而且我们可以看到两个参数都不能改变,那么必须声明为:

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

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

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

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

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

如果你想让你的运算符重载的行为像内置的运算符,那么这个规则是非常简单的; 该标准定义了内置运算符的行为方式,并指出内置结果是rvalue还是lvalue

你应该使用的规则是:

  • 如果内置的运算符返回一个rvalue那么你的重载应该返回一个引用
  • 如果内置返回一个lvalue那么你的重载应该返回一个值

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

例如,KennyTM在另一个回答中指出, <<>>操作符的stream重载会返回对左操作数的引用,而不是内置函数的工作方式。 但是stream接口的devise者是这样做的,所以streamI / O可以被链接。

根据运营商的不同,您可能需要按价值返还。

当两者都可以使用,但在运营商+ =你可以考虑以下几点:

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

通常情况下,您通过引用来返回操作的值,例如=+= 。 所有其他操作都是按值返回。

虽然这是更经验的法则。 你可以任意devise你的操作员。