Каков правильный способ передачи права собственности на std::vector<unique_ptr<int> >
класс строится?
Ниже приведено кодовое представление того, что я хочу сделать. Я понимаю, что это не правильно (не будет компилироваться) и нарушает «уникальность», передам ли я вектор конструктору по значению или по ссылке. Я хочу, чтобы Foo был новым владельцем вектора, и хочу, чтобы вызывающая функция отказалась от владения. Мне нужен конструктор, чтобы взять std::unique_ptr<std::vector<std::unique_ptr<int> > >
сделать это?
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;
}
Любая помощь будет высоко ценится — я искал сеть в поисках правильного способа сделать это. Спасибо!
std::unique_ptr<T>
это не копируемый, но подвижный тип. Наличие только для перемещения типа в std:vector<T>
сделать std::vector<T>
только для перемещения. Чтобы компилятор автоматически перемещал объекты, вам нужно иметь r-значение для move-construction или move-assignment. В вашем конструкторе объект vecOfIntPtrsOwnedByCaller
является l-значением, хотя тот, который, несмотря на свое название, уже имеет int
s: они были «украдены» от вызывающей стороны, когда вызывающая сторона создала объект. Чтобы перейти от значения l, вам нужно использовать std::move()
(или что-то эквивалентное):
Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
{
_vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller);
}
или, предпочтительнее
Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
: _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller))
{
}
В последнем подходе избегают сначала конструирования элемента по умолчанию, а затем присваивания ему перемещения и, вместо этого, непосредственного конструирования элемента. Думаю, я бы также сделал аргумент ссылкой на r-значение, но это не обязательно.
Обратите внимание, что вы можете создавать объекты типа Foo
только из того, что может быть связано с r-значением, например:
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
}
Других решений пока нет …