What is the state of an object after it has been moved - through a reference to its base class?

Let's assume there is a hierarchy of two classes:

class Base {};
class Foo: public Base {};

      

Which are used as follows:

Foo foo;
Base &base = foo;
Base moved = std::move(base);

      

In what state foo

after such a move? Does the Standard provide any requirements for restrictions on such code?

+3


source to share


2 answers


The standard makes no such requirement for move constructors for C ++ classes that are not part of the standard library. The library writer can do whatever he wants. For components that are part of the standard library, the C ++ 17 standard says something (focus)

Β§ 20.5.5.15 Moving from the library types state [lib.types.movedfrom]

Objects of types defined in the C ++ standard library can be moved from (15.8). Move operations can be specified explicitly or implicitly generated. Unless otherwise noted, such relocated objects are placed in a valid but undefined state.

For standard library classes that are part of the inheritance hierarchy, you will need to consult the documentation to see what happens when you try to move the construct of the base object out of the base class. rvalue refers to a derived class object. So if you could point out which class in particular bothers you, I might try and help more.




Not sure how relevant this is to your question, but in regards to what will actually happen in such a constructor. Remember that the virtual function mechanism is disabled in the constructors for the object to be created, but not for the referenced object. In the following example

class Base {
public:
    virtual vector<int> extract_vector() { ... }

    // Move constructor can use virtual functions on the other object
    Base(Base&& other) {
        this->vec = other.extract_vector();
    }

private:
    std::vector<int> vec;
};

class Foo : public Base {
public:
    vector<int> extract_vector() override { ... }

private:
    // this does something Β―\\_(ツ)_/Β― 
    SpecialVectorAdaptor<std::vector<int>> vec;
};

      

The virtual function extract_vector

on other

in the move constructor for will be called Base

, and you can use virtual methods on the object other

. But you cannot use such virtual methods for the class to be created.




In short , the behavior of the code you've shown will depend solely on the implementation of the classes in question.

+1


source


In your particular case, nothing happens as both Base

and Foo

are empty classes.

For a more interesting situation that, as Base

well as Foo

have some movable elements (or base), as Base

has a user-defined motion designer will use the default constructor move. This will move the Base

piece Foo

in moved

, but leave it intact.
For example, after

struct Base      { std::unique_ptr<int> X; };
struct Foo: Base { std::unique_ptr<int> Y; };

Foo foo;
foo.X.reset(new int);
foo.Y.reset(new int);
Base &base = foo;
Base moved = std::move(base);

      



foo.X

empty ( nullptr

) with original value moved to moved

, but still foo.Y

still retains its original value.

This demonstrates that when navigating away from a link, you are potentially changing the state of the referenced object, which can create all sorts of unwanted effects and is best avoided.

+1


source







All Articles