What is the proper way of transferring ownership of a std::vector<unique_ptr<int> >
to a class being constructed?
Below is a code representation of what I want to do. I realize it is not correct (won't compile) and violates "uniqueness" whether I pass the vector to the constructor by value or by reference. I want Foo to be the new owner of the vector, and want the calling function to relinquish ownership. Do I need the constructor to take a std::unique_ptr<std::vector<std::unique_ptr<int> > >
to do this?
Foo.h
class Foo
{
public:
Foo(vector<std::unique_ptr<int> > vecOfIntPtrsOwnedByCaller);
private:
vector<std::unique_ptr<int> > _vecOfIntPtrsOwnedByFoo;
}
Foo.cpp
Foo::Foo(std::vector<std::unique_ptr< int> > vecOfIntPtrsOwnedByCaller)
{
_vecOfIntPtrsOwnedByFoo = vecOfIntPtrsOwnedByCaller;
}
Any help would be much appreciated - I've scoured the net looking for the correct way to do this. Thanks!
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
}