Grzegorz Szpetkowski
Grzegorz Szpetkowski

Reputation: 37914

Confusion about result of overloaded assignment operator being lvalue or not

I have some doubt, reading this paragraph from the "Beginning Visual C++ 2013" book:

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.

The class CMessage is defined as follows:

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

along with main function defined as:

int main()
{
    CMessage motto1, motto2;
    CMessage motto3("A miss is as good as a mile.");

    (motto1 = motto2) = motto3;

    motto1.ShowIt();
    motto2.ShowIt();
    motto3.ShowIt();
}

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

My understanding is that code is flawed, because in final result, motto1 wouldn't be changed, but other than that it is perfectly legal, because returned copy (involving a copy constructor) is a lvalue.

Upvotes: 0

Views: 77

Answers (2)

eerorika
eerorika

Reputation: 238311

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

Yes, this particular overloaded operator does return a value, so the value category of the call expression is a (p)rvalue. The book is correct about that.

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

If the intention is to assign motto3 to motto1, then yes, the code is indeed flawed. However, the reason that the book gives:

compiler will not allow a member function call using an rvalue

Is not true. It is true for c, and possibly for pre-standard versions of c++, but not true for standard c++.

Upvotes: 1

M.M
M.M

Reputation: 141554

CMessage operator=(const CMessage& aMess) returns by value. This means that a temporary object is returned and the value category of (motto1 = motto2) is prvalue. Note that nothing is special about operator= here, it would be the same for any function returning by value.

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

In ISO C++ that is true...

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

The returned copy is a temporary object. The word "lvalue" is a value category of expressions; it is not an adjective that applies to objects. The value category of an expression consisting of a function call where that function returns by value, is prvalue, not lvalue.

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

In ISO C++ it is fine to call a member function on an rvalue. I can't speak to Visual C++ 2013.

Upvotes: 3

Related Questions