Правильный способ передачи права собственности на std :: vector & lt; станд :: unique_ptr & л; INT & GT; & GT; в строящемся классе

Каков правильный способ передачи права собственности на 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;
}

Любая помощь будет высоко ценится — я искал сеть в поисках правильного способа сделать это. Спасибо!

20

Решение

std::unique_ptr<T> это не копируемый, но подвижный тип. Наличие только для перемещения типа в std:vector<T> сделать std::vector<T> только для перемещения. Чтобы компилятор автоматически перемещал объекты, вам нужно иметь r-значение для move-construction или move-assignment. В вашем конструкторе объект vecOfIntPtrsOwnedByCaller является l-значением, хотя тот, который, несмотря на свое название, уже имеет ints: они были «украдены» от вызывающей стороны, когда вызывающая сторона создала объект. Чтобы перейти от значения 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
}
20

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]