Ответ 1
std::unique_ptr<T>
- это не скопируемый, но подвижный тип. Наличие типа "только для перемещения" в std:vector<T>
также делает перемещение std::vector<T>
только для перемещения. Чтобы компилятор автоматически перемещал объекты, вам нужно иметь значение r для перемещения-перемещения или назначения перемещения. Внутри вашего конструктора объект 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
}