我有一些疑问,请阅读" Beginning Visual C ++ 2013"书:
当您将剩余的赋值操作表示为显式时 重载函数调用,最终变为:
(motto1.operator=(motto2)).operator=(motto3);
现在,你有一个从中返回对象的情况
operator=()
函数用于调用operator=()
函数。如果 返回类型只是CMessage
,这不合法,因为a 原始对象的临时副本返回,这将是一个 rvalue ,编译器不允许使用成员函数调用 右值。确保这一点的唯一方法是编译并正常工作 是返回一个引用,这是一个左值。
班级CMessage
的定义如下:
class CMessage
{
private:
char* pmessage;
public:
void ShowIt() const
{
cout << endl << pmessage;
}
CMessage(const char* text = "Default message")
{
cout << endl << "Constructor called.";
pmessage = new char[strlen(text) + 1];
strcpy(pmessage, text);
}
CMessage(const CMessage& initM)
{
cout << "Copy constructor called" << endl;
pmessage = new char[strlen(initM.pmessage) + 1];
strcpy(pmessage, initM.pmessage);
}
~CMessage()
{
cout << "Destructor called." << endl;
delete[] pmessage;
}
CMessage operator=(const CMessage& aMess)
{
delete[] pmessage;
pmessage = new char[strlen(aMess.pmessage) + 1];
strcpy(this->pmessage, aMess.pmessage);
return *this;
}
};
以及main
函数定义为:
int main()
{
CMessage motto1, motto2;
CMessage motto3("A miss is as good as a mile.");
(motto1 = motto2) = motto3;
motto1.ShowIt();
motto2.ShowIt();
motto3.ShowIt();
}
问题:运算符函数是否确实返回了一个右值,或者该书对于该语句是不是很简单?
我的理解是代码存在缺陷,因为在最终结果中,motto1
不会被更改,但除此之外它是完全合法的,因为返回的副本(涉及复制构造函数)是左值。
答案 0 :(得分:3)
CMessage operator=(const CMessage& aMess)
按值返回。这意味着返回临时对象,(motto1 = motto2)
的值类别为 prvalue 。请注意,此处operator=
没有什么特别之处,对于按值返回的任何函数都是相同的。
我的理解是代码存在缺陷,因为在最终结果中,motto1不会被改变,但除此之外它完全合法,
在ISO C ++中是真的......
因为返回的副本(涉及复制构造函数)是左值。
返回的副本是临时对象。 “左值”这个词是表达式的值类别;它不是一个适用于对象的形容词。由函数调用组成的表达式的值类别是 prvalue ,而不是 lvalue 。
编译器不允许使用rvalue进行成员函数调用。
在ISO C ++中,可以在rvalue上调用成员函数。我无法与Visual C ++ 2013对话。
答案 1 :(得分:1)
操作符函数是否真的返回了一个右值,或者该书对该语句是不是很简单?
是的,这个特殊重载的运算符确实返回一个值,因此调用表达式的值类别是(p)rvalue。这本书是正确的。
我的理解是代码存在缺陷,因为在最终结果中,motto1不会被改变
如果打算将motto3
分配给motto1
,那么是的,代码确实存在缺陷。但是,这本书的原因是:
编译器不允许使用rvalue
进行成员函数调用
不是真的。这对c来说是正确的,并且可能对于c ++的预标准版本,但对于标准c ++则不然。