Consider this snippet:
class X;
void MoveAppend(vector<X>& src, vector<X>& dst) {
dst.reserve(dst.size() + src.size());
for (const X& x : src) dst.push_back(x);
src.clear();
}
If we assume that class X
implements move semantics, how can I efficiently implement MoveAppend
?
Just do:
#include <iterator>
#include <algorithm>
// ...
void MoveAppend(std::vector<X>& src, std::vector<X>& dst)
{
if (dst.empty())
{
dst = std::move(src);
}
else
{
dst.reserve(dst.size() + src.size());
std::move(std::begin(src), std::end(src), std::back_inserter(dst));
src.clear();
}
}
If dst
is empty, a move-assignment from src
to dst
will do the job - that will be as cheap as it can be, just "stealing" the array encapsulated by src
so that dst
will point to it afterwards.
If dst
is not empty, elements appended to dst
will be move-constructed from elements in src
. After the call to std::move()
, src
will not be empty - it will contain "zombie" moved-from elements. That's why the call to clear()
is still necessary.