Given the simple code
#include <array>
#include <vector>
int main() {
std::vector<std::array<int,3>> v;
v.emplace_back(std::array<int,3>{1,2,3});
}
I'm first of all worried about what is really going on.
My understanding of emplace_back
is that it constructs an element (in this case an std::array<int,3>
with values 1
, 2
, 3
) in-place by forwarding its argument(s) to that element's constructor.
But which constructor? Since we are passing an object of the same type of the element we want to emplace, I guess the move constructor is selected, as we're passing a temporary, or the copy ctor if the move ctor is deleted (implicitly or explicitly). Besides, we are first of all constructing that temporary, and that's not done in place, right?
So we are basically calling the "normal" (???) constructor of std::array<int,3>
by passing to it 1
, 2
, and 3
as arguments, thus getting back a temporary, which is passed to the copy ctor of std::array<int,3>
which constructs the copy in place or, preferably, to the move ctor of std::array<int,3>
which (?) copies the underlying C-style pointer?
It should be clear this simple example is confusing me a lot.
To confuse me even more is the doubt that if I really wanted to take advantage of emplace_back
, I could pass to it only the arguments to the std::array<int,3>
, as in
#include <array>
#include <vector>
int main() {
std::vector<std::array<int,3>> v;
v.emplace_back(1,2,3);
}
Let me try to clarify a bit. First of, std::array<>
is an aggregate. It does not have any user-defined constructors at all.
So it is quasi-movable (technical term is trivially movable), meaning you can construct it from temporary, but it is going to simply copy the underlying array. So what the code ends up doing is copying supplied array into the newly allocated vector element.
You would achieve identical results (but will do slightly less typing) if you replace the emplace_back
with push_back
like following:
v.push_back({1,2,3});
And emplace_back(1, 2, 3)
doesn't compile because std::array<>
does not have any constructors which take more than one argument.