Код ниже дает ошибку:
use of deleted function ‘constexpr B::B(const B&)’
теперь я знаю, что это происходит потому, что конструктор копирования (преднамеренно) неявно удаляется путем указания конструктора перемещения, а копирование вектора вызывает вызовы (удаленного) конструктора копирования. Думаю, я также понимаю, почему используются конструктор копирования и оператор присваивания вектора. Я явно хочу использовать конструктор перемещения и оператор присваивания: переместить объект, а также переместить вектор, который он содержит. Так, как заставить мой конструктор перемещения / оператор присваивания использовать оператор конструктора перемещения / присваивания?
Вот код:
#include <vector>
class B {
private:
/* something I don't want to copy */
public:
B() {};
B(B&& orig) {/* move contents */};
B& operator=(B&& rhs) {
/* move contents */
return *this;
};
};
class A {
private:
vector<B> vec;
public:
A() : vec() {};
A(A&& orig) : vec(orig.vec) {};
A& operator=(A&& rhs) {
vec = rhs.vec;
return *this;
};
};
Чтобы убедиться, что конструктор «move» и операторы присваивания вызываются, вы необходимо предоставить объект правильной категории значения. Категория значений используется, чтобы определить, какие операторы и конструкторы могут быть использованы.
использование std::move
изменить категория стоимости (от lvalue в данном случае) до xvalue (rvalue, из которого можно переместиться).
// ...
A(A&& orig) : vec(std::move(orig.vec)) {};
A& operator=(A&& rhs) {
vec = std::move(rhs.vec);
return *this;
};
move
не копирует и не изменяет объект каким-либо образом, это просто приведение к rvalue-ссылке типа аргумента — следовательно, изменение категории значения.
Просто позвони std::move
на векторы в выражении, в котором вы хотите перейти от них:
class A {
private:
vector<B> vec;
public:
A() : vec() {};
A(A&& orig) : vec(std::move(orig.vec)) {};
// ^^^^^^^^^
A& operator=(A&& rhs) {
vec = std::move(rhs.vec);
// ^^^^^^^^^
return *this;
};
};
Даже если вы берете в Rvalue ссылки, rhs
а также orig
все еще являются lvalues в функции, поэтому вам нужно вызвать std::move
на них.
Если все члены вашего класса являются объектами классов с правильно определенным конструктором перемещения / оператором присваивания, вам лучше использовать дефолт переместить конструктор / оператор присваивания для вашего класса. Это было бы намного проще и менее подвержено ошибкам и обеспечило бы вызов конструктора перемещения / оператора присваивания членов класса.
В вашем конкретном примере это будет:
class A
{
private:
vector<B> vec;
public:
A() : vec() {};
A(A&&) = default;
A& operator=(A&&) = default;
};