Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should the rvalue be valid after a move?

Lets say we have the following class:

class Foo
{
public:
    Foo() { _bar=new Bar };
    Foo(const Foo &right) { _bar=new Bar(right.bar); };
    Foo(Foo &&right) { _bar=right._bar;  right.bar=new Bar(); };

    ~Foo() { delete _bar; }

    Foo &operator=(const Foo &right) { _bar->opertor=(right.bar); return *this;}
    Foo &operator=(Foo &&right) { std::swap(_bar, right._bar); return *this;}

    void func() { _bar->test=1 };

private:
    Bar *_bar;
};

is it legitimate to alter it to the following and expect the end user to know that after the move is performed that the rvalue is no longer valid (in that calling anything other than the assignment operator could crash)?

class Foo
{
public:
    Foo() { _bar=new Bar };
    Foo(const Foo &right) { _bar=new Bar(right.bar); };
    Foo(Foo &&right) { _bar=right._bar;  right.bar=nullptr; };

    ~Foo() { if(_bar != nullptr) delete _bar; }

    Foo &operator=(const Foo &right) 
    { 
         if(_bar == nullptr) 
             _bar=new Bar();
         _bar->opertor=(right.bar); 
         return *this;
    }

    Foo &operator=(Foo &&right)
    {
        if(_bar != nullptr)
            delete _bar;  
        _bar=right._bar; 
        right._bar=nullptr; 
        return *this;
    }

    void func() { _bar->test=1 };

private:
    Bar *_bar;
};

my concern comes from the fact that func (and all other functions in the class) assume that _bar exists.

like image 229
Krazer Avatar asked Dec 22 '25 14:12

Krazer


2 Answers

In principle it may become invalid, though you might want consider leaving it in an assignable state (which your original implementation, hence edited, did not do). This would follow the policy of the standard library, which says:

Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. That is, only the functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from

I'd recommend reimplementing the assignment operator such that it swaps "this" object with a newly constructed one. This is generally a good way to avoid introducing incorrect behaviour when implementing assignments.

like image 147
Josef Grahn Avatar answered Dec 24 '25 03:12

Josef Grahn


A moved-from object is supposed to be in a valid but unspecified state. Note that this is a recommendation but not an absolute requirement of the standard.

Your second code will break if a normal operation is performed on it afterwards (specifically, the copy-assignment operator).

If _bar == nullptr is a valid state then your copy-assignment operator is bugged; if it is not a valid state then I would say your move-constructor is bugged.

NB. In the second code, the if check in the destructor is redundant, as it is legal to delete a null pointer.

like image 44
M.M Avatar answered Dec 24 '25 04:12

M.M



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!