shared_ptr make_unique c++ c++11 stdvector unique-ptr ownership

c++ - shared_ptr - make_unique



Forma correcta de transferir la propiedad de un std:: vector<std:: unique_ptr<int>> a una clase que se está construyendo (1)

¿Cuál es la forma correcta de transferir la propiedad de un std::vector<unique_ptr<int> > a una clase que se está construyendo?

A continuación se muestra una representación en código de lo que quiero hacer. Me doy cuenta de que no es correcto (no compilará) y viola la "unicidad" si le paso el vector al constructor por valor o por referencia. Quiero que Foo sea el nuevo propietario del vector y que la función de llamada renuncie a la propiedad. ¿Necesito que el constructor tome un std::unique_ptr<std::vector<std::unique_ptr<int> > > para hacer esto?

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; }

Cualquier ayuda sería muy apreciada, he buscado en la red buscando la forma correcta de hacerlo. ¡Gracias!


std::unique_ptr<T> es un tipo que no se puede copiar pero que se puede mover. Tener un tipo de solo movimiento en un std:vector<T> hace que el std::vector<T> solo se mueva. Para que el compilador mueva objetos automáticamente, debe tener un valor r para la construcción de movimientos o la asignación de movimientos. Dentro de su constructor, el objeto vecOfIntPtrsOwnedByCaller es un valor l, aunque uno de los cuales, a pesar de su nombre, ya posee los int . int : fueron "robados" del llamante cuando el llamante creó el objeto. Para pasar de un valor l, necesita usar std::move() (o algo equivalente):

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) { _vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller); }

o, preferible

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) : _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller)) { }

Este último enfoque evita primero la construcción por defecto del miembro y luego la asignación de movimiento a él y, en su lugar, move-construye el miembro directamente. Supongo que también haría del argumento una referencia de valor r, pero esto no es necesario.

Tenga en cuenta que puede construir objetos de tipo Foo solo a partir de algo que pueda vincularse a un valor r, por ejemplo:

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 }