In order to understand the rule of five, I came up with this:
#include <iostream>
#include <vector>
class A
{
public:
A(int y)
{
std::cout << "constructed\n";
x = new int[y];
}
~A()
{
std::cout << "destructed\n";
delete[] x;
}
A(const A &other)
{
std::cout << "copied\n";
if (other.x != nullptr)
x = new int[sizeof(other.x) / sizeof(other.x[0])];
}
A(A && other) :
x(other.x)
{
std::cout << "moved\n";
other.x = nullptr;
}
A& operator=(A other)
{
std::cout << "assignments\n";
std::swap(x, other.x);
return *this;
}
int *x;
};
class B
{
private:
std::vector<A> a;
public:
B()
{
for (int i = 0; i < 5; i++)
a.emplace_back(A(1));
std::cout << "----------------------\n";
for (int i = 0; i < 5; i++)
a.push_back({ 2 });
}
};
int main()
{
B *b = new B();
std::cin.get();
}
If, instead, I use emplace_back and push_back 1 time each, I get this output, regardless of the order I call each method:
constructed
moved
destructed
----------------------
constructed
moved
destructed
moved
destructed
I accept that. However, if I use the code as wrote above, I get some tricky pattern:
constructed
moved
destructed
constructed
moved
destructed
moved
destructed
constructed
moved
moved
destructed
destructed
moved
destructed
constructed
moved
moved
moved
destructed
destructed
destructed
moved
destructed
constructed
moved
moved
moved
moved
destructed
destructed
destructed
destructed
moved
destructed
----------------------
constructed
moved
destructed
constructed
moved
moved
moved
moved
moved
moved
destructed
destructed
destructed
destructed
destructed
destructed
moved
destructed
constructed
moved
destructed
constructed
moved
destructed
constructed
moved
moved
moved
moved
moved
moved
moved
moved
moved
destructed
destructed
destructed
destructed
destructed
destructed
destructed
destructed
destructed
moved
destructed
What explains so many "moved" and "destructed"? Also, can we state that emplace_back is better than push_back just by this output?