请教关于函数返回临时副本的疑问
本帖最后由 dwjgwsm 于 2013-07-06 11:34:29 编辑 《Ivor Hortonn's Beginning Visual C++ 2012》第295页的赋值运算符函数采用了返回引用的方式CMessage&:
CMessage& operator=(const CMessage& aMess)
{
if(this != &aMess) // Check addresses are not equal
{
// Release memory for 1st operand
delete[] pmessage;
pmessage = new char[strlen(aMess.pmessage) + 1];
// Copy 2nd operand string to 1st
strcpy_s(this->pmessage, strlen(aMess.pmessage)+1, aMess.pmessage);
}
// Return a reference to 1st operand
return *this;
}
其解释是,如果直接返回对象,以下语句将不能正确工作:
//motto1,motto2,motto3均为CMessage对象
(motto1 = motto2) = motto3 //motto1 = motto2返回的是原始对象的临时副本,临时副本是rvalue,
//rvalue不能调用成员函数,故(motto1.operator=(motto2)).operator=
//(motto3)无法正确编译。
既然如此,我想问的是,第300页的如下函数为什么却可以正确处理三个以上对象的连加?
CBox operator+(const CBox& aBox) const
{
// New object has larger length & width, and sum of heights
return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length,
m_Width > aBox.m_Width ? m_Width : aBox.m_Width,
m_Height + aBox.m_Height);
}
谢谢各位大大! 函数返回临时副本
[解决办法]
不同.
A + B + C 这里是把 operator+ 的返回值做为参数, 不会修改返回的值.
(A = B) = C 这里是对 operator= 的返回值赋值, 要修改那个返回值.
[解决办法]
A+B+C并没有这个问题,因为我只关心它的最终返回值,并不关心它的计算的是10 + 5还是“10的副本”+5,哪怕你把10复制上10次,然后用它去加5,结果也是15,没什么区别。
但(A=B)=C不同,最后那次赋值发生在对象A上还是发生在临时对象上,二者有着巨大的区别,这将决定对象A最终的状态。
编译器不允许使用rvalue调用成员函数吗?我确实不知道这一点,如果真是这样,那我上面所说的:“可以对非简单类型的临时对象赋值”就是错误的,std::ref可能是用的const赋值操作符来实现的。
不过,下面的代码在我的编译器中编译通过:
class x
{
public:
x operator = ( x & a)
{
return * this;
}
};
int main()
{
x a, b, c;
(a = b ) = c;
}
所以我一向都把赋值操作符的返回值声明为T const &或T const类型,从而来阻止(a = b ) = c这种表达式的编译。