Move-construct object with new placement

Is it necessary for UB to move-build an object through the placement of new?

Let's say I have this code:

class Foo { public: Foo() { foo_ = new int; } ~Foo() { delete foo_; } Foo(Foo &&f) { foo_ = std::swap(f.foo_, foo_); } private: int* foo_; } void bar() { void* pMem = malloc(sizeof(Foo)); Foo f1; // move-construct with placement new: new((Foo*)pMem) Foo(std::move(f1)); // f2 in *pMem // now f1 will contain a pointer foo_ of undefined value // when exiting scope f1.~Foo(){} will exhibit UB trying to delete it } 

If this is not obvious, the f1 member foo_ will be undefined after creating the second foo by placing new and move construction (this undefined value comes from the uninitialized Foo f2 foo_ inside its move constructor, because the values ​​are changed )

Thus, when exiting the bar () area, f1 destructor will try to delete the invalid (uninitialized) pointer.

+2
c ++ c ++ 11 placement-new move-constructor
source share
1 answer

This has nothing to do with posting a new one. This code would have the same problem:

 void bar() { Foo f1; Foo f2(std::move(f1)); } 

Each constructed object will ultimately be destroyed, so it doesn’t matter if you use new-new or not, your move constructor is messy, leaving the moved object in an invalid state.Transition from the object does not mean that it will not be destroyed. This will. You must leave the actual object behind when you move from it.

 Foo(Foo &&f) : foo_(nullptr) { std::swap(f.foo_, foo_); } 

will fix the error.

+5
source share

All Articles