If the move constructor of your class is noexcept then std::vector will allocate new memory and then move construct your objects in the new memory. If it's not "noexcept" it will copy construct them. If it copy constructs them, then those objects still need to be destroyed before deallocating the old buffer. However why is it the case that if the object is moved it still calls the destructors on all the old objects. I don't see why this is necessary. Any destructor call on a moved-from object is not going to do anything, apart from some conditional checks. You could argue that the "object is technically not destroyed", and that's true, but since that memory is being deallocated, and the next time that memory is used the only defined way to access objects there is to construct them first, I don't see why this needs to be done:
struct Foo
{
void* buffer;
Foo() : buffer(new char[16]) {}
Foo(Foo&& other) { buffer = other.buffer; if (other.buffer != nullptr) other.buffer = nullptr; }
~Foo()
{
if (buffer != nullptr) delete buffer;
}
};
int main()
{
Foo foo;
Foo foo2 = std::move(foo);
foo.~Foo(); /* NO EFFECT */
/* BUT ASSUMING WE DIDN'T CALL THE CONSTRUCTOR, WE JUST CONSTRUCT OVER IT */
new (&foo) Foo{};
/* THEN THE OLD FOO CEASES TO EXIST EVEN IF THE DESTRUCTOR IS NEVER CALLED */
}
Here is a quick program showing that std::vector calls the destructors on the old moved-from objects:
#include <iostream>
struct Foo
{
Foo() {}
Foo(uint32 id) { }
Foo(const Foo& other)
{
std::cout << "Copy constructor called\n";
}
Foo(Foo&& other) noexcept
{
std::cout << "Move constructor called\n";
};
~Foo()
{
std::cout << "Destructor called\n";
}
};
int main()
{
Foo foo;
std::vector<Foo> v;
v.push_back(std::move(foo));
v.push_back(std::move(foo));
v.push_back(std::move(foo));
v.push_back(std::move(foo));
}