There is the following code:
#include <iostream>
#include <vector>
class Test {
public:
Test() {}
Test(int x) : x(x) {}
Test(const Test&) noexcept = delete;
Test& operator=(const Test&) noexcept = delete;
Test(Test&& r) noexcept { x = std::move(r.x); }
Test& operator=(Test&& r) noexcept {
std::cout << "move";
x = std::move(r.x);
return *this;
}
~Test() noexcept { std::cout << x; }
private:
int x;
};
int main() {
std::vector<Test> v;
v.reserve(5);
v.emplace_back(1);
v.emplace_back(2);
v.emplace_back(3);
v.emplace_back(4);
v.emplace_back(5);
v.reserve(10);
}
output:
1234512345
We see the destructors, but do not see the move assignment, so we can conclude that the object is being copied instead of moved. This question has already been discussed in several topics, but nowhere is there a specific answer.
There is a workaround using unique_ptrs:
#include <iostream>
#include <vector>
#include <memory>
class Test {
public:
Test() {}
Test(int x) : x(x) {}
Test(const Test&) noexcept = delete;
Test& operator=(const Test&) noexcept = delete;
Test(Test&& r) noexcept { x = std::move(r.x); }
Test& operator=(Test&& r) noexcept {
std::cout << "move";
x = std::move(r.x);
return *this;
}
~Test() noexcept { std::cout << x; }
private:
int x;
};
int main() {
std::vector<std::unique_ptr<Test>> v;
v.reserve(5);
v.emplace_back(std::make_unique<Test>(1));
v.emplace_back(std::make_unique<Test>(2));
v.emplace_back(std::make_unique<Test>(3));
v.emplace_back(std::make_unique<Test>(4));
v.emplace_back(std::make_unique<Test>(5));
v.reserve(10);
}
output:
12345
All code tested on compilers gcc 5.1 - 10.2
Why does copying of objects occur when allocating memory in a vector instead of moves? Why is the move semantics not used in the first block of code, what is the reason for this behavior?