在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你的操作员。