Home > Blockchain >  std::move with polymorphic move assignment operator and memory safety
std::move with polymorphic move assignment operator and memory safety

Time:06-23

I was wondering if the following code was safe, considering the child object is implicitly converted to type Parent and then moved from memory. In other words, when passing other to Parent::operator=(Parent&&) from Child::operator(Child&&), is the entire object "moved" with the parent call, or just the underlying Parent object?

class Parent
{
public:
     // Constructors

     Parent& operator=(Parent&& other) noexcept
     {
          if (this == &other)
               return *this;

          str1_ = std::move(other.str1_);
          str2_ = std::move(other.str2_);
          return *this;
     }

protected:
     std::string str1_, str2_;
};

class Child : public Parent
{
public:
     // Constructors

     Child& operator=(Child&& other) noexcept
     {
          if (this == &other)
               return *this;

          // Are the following 2 lines memory safe?
          Parent::operator=(std::move(other));
          str3_ = std::move(other.str3_);

          return *this;
     }

private:
     std::string str3_;
};

CodePudding user response:

What you are doing is safe. You are just passing a reference to the base-class subobject to the base assignment operator. std::move doesn't move anything. It just makes an xvalue out of an lvalue, so that a rvalue reference may bind to it. The binding here is to a subobject because Parent is a base class type of Child.

In fact you are exactly replicating the behavior that a defaulted move assignment operator would have (except that it wouldn't check for self-assignment, which is pointless if you are only forwarding to other assignment operators), which begs the question why you are defining it at all? Just follow the rule-of-zero and don't declare a move assignment operator.

This goes for both Parent's and Child's move assignment operator.

  • Related