What is the proper way of transferring ownership of a std::vector
to a class being constructed?
Below is a code representation
std::unique_ptr<T>
is a non-copyable but movable type. Having a move-only type in a std:vector<T>
make the std::vector<T>
move-only, too. To have the compiler automatically move objects, you need to have an r-value for move-construction or move-assignment. Within your constructor the object vecOfIntPtrsOwnedByCaller
is an l-value, although one which, despite its name, already owns the pointed to int
s: they got "stolen" from the caller when the caller created the object. To move from an l-value, you need to use std::move()
(or something equivalent):
Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
{
_vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller);
}
or, preferable
Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
: _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller))
{
}
The latter approach avoid first default-constructing the member and then move-assigning to it and, instead, move-constructs the member directly. I guess, I would also make the argument an r-value reference but this isn't necessary.
Note, that you can construct objects of type Foo
only from something which can be bound to an r-value, e.g.:
int main() {
Foo f0(std::vector<std::unique_ptr<int>>()); // OK
std::vector<std::unique_ptr<int>> v;
Foo f1(v); v// ERROR: using with an l-value
Foo f2{v}; v// ERROR: using with an l-value
Foo f3 = v; // ERROR: using with an l-value
Foo f4(std::move(v)); // OK: pretend that v is an r-value
}