问题
Is it not UB to move-construct an object via placement 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 it's not obvious, f1's member foo_ will have an undefined value after constructing the second foo by placement new and move construction (this undefined value comes from the uninitialized Foo f2's foo_ inside its move-constructor because the values are swapped)
Thus, when exiting the scope of bar(), f1's destructor will try to delete an invalid (uninitialized) pointer.
回答1:
This has nothing to do with placement new. This code would have the exact same problem:
void bar() {
Foo f1;
Foo f2(std::move(f1));
}
Every constructed object will get destructed eventually, so it doesn't matter if you use placement-new or not, your move-constructor messes up by leaving the moved-from object in a invalid state. Moving from an object doesn't mean it won't get destructed. It will. You have to let a valid object behind when you move from it.
Foo(Foo &&f) : foo_(nullptr) {
std::swap(f.foo_, foo_);
}
will fix the bug.
来源:https://stackoverflow.com/questions/38171964/move-construct-object-with-placement-new