对重载赋值运算符的结果是否为左值感到困惑

Confusion about result of overloaded assignment operator being lvalue or not

我有一些疑问,阅读"Beginning Visual C++ 2013"书中的这段话:

When you express the remaining assignment operation as the explicit overloaded function call, this ultimately becomes:

(motto1.operator=(motto2)).operator=(motto3);

Now, you have a situation where the object returned from the operator=() function is used to call the operator=() function. If the return type is just CMessage, this will not be legal because a temporary copy of the original object is returned which will be an rvalue, and the compiler will not allow a member function call using an rvalue. The only way to ensure this will compile and work correctly is to return a reference, which is an lvalue.

classCMessage定义如下:

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

问题:运算符函数真的 returns 一个右值,还是书上关于那个陈述的简单错误?

我的理解是代码有缺陷,因为在最终结果中,motto1不会改变,但除此之外它是完全合法的,因为返回的副本(涉及复制构造函数)一个左值。

Does operator function really returns an rvalue or the book is simpy wrong about that statement?

是的,这个特定的重载运算符 return 一个值,因此调用表达式的值类别是 (p)rvalue。这本书是正确的。

My understanding is that code is flawed, because in final result, motto1 wouldn't be changed

如果意图是将motto3分配给motto1,那么是的,代码确实有缺陷。不过书上给出的理由:

compiler will not allow a member function call using an rvalue

不正确。这对 c 是正确的,可能对 c++ 的准标准版本也是如此,但对标准 c++ 不是这样。

CMessage operator=(const CMessage& aMess) returns 按值。这意味着返回一个临时对象并且(motto1 = motto2)的值类别是prvalue。请注意,这里的 operator= 没有什么特别之处,对于任何按值返回的函数都是一样的。

My understanding is that code is flawed, because in final result, motto1 wouldn't be changed, but other than that it is perfectly legal,

在 ISO C++ 中是这样...

because returned copy (involving a copy constructor) is a lvalue.

返回的副本是一个临时对象。单词 "lvalue" 是表达式的 值类别 ;它不是适用于对象的形容词。由函数调用组成的表达式的值类别,其中该函数 returns 按值计算,是 prvalue,而不是 lvalue.

compiler will not allow a member function call using an rvalue.

在 ISO C++ 中,可以在右值上调用成员函数。我无法与 Visual C++ 2013 对话。