Конструктор с семантикой перемещения и копирования
Мне нужно написать конструктор для моего класса, который принимает два std::vector в качестве аргументов. Эти векторы должны быть скопированы в приватные члены, и я хотел бы использовать семантику перемещения, когда мои пользователи передают временную ссылку или ссылку на значение, а в противном случае семантику копирования. Это общая проблема, которая приводит к написанию копии и конструктора перемещения для обработки конструкции, начинающейся с объекта того же класса. Но в моем случае я строю, исходя из двух разных параметров (векторов), каждый из которых может быть либо lvalue, либо rvalue; поэтому я должен разобраться с четырьмя разными случаями:
MyClass(const std:vector<float> &v1, const std::vector<float> &v2):
_v1(v1), _v2(v2) {};
MyClass(const std:vector<float> &v1, std::vector<float> &&v2):
_v1(v1), _v2(std::move(v2)) {};
MyClass(std:vector<float> &&v1, const std::vector<float> &v2):
_v1(std::move(v1)), _v2(v2) {};
MyClass(std:vector<float> &&v1, std::vector<float> &&v2):
_v1(std::move(v1)), _v2(std::move(v2)) {};
каждая из которых требует небольшого изменения одной и той же логики конструктора с неприятным распространением похожих фрагментов кода. Ситуация ухудшится в геометрической прогрессии, если добавить другой параметр вектора. Какова лучшая практика, чтобы справиться с этой ситуацией? Благодарю.
2 ответа
Вы можете просто передать по значению:
MyClass(std::vector<float> v1, std::vector<float> v2)
: _v1(std::move(v1)), _v2(std::move(v2)) {}
Это происходит за счет одного дополнительного вызова конструктора перемещения для каждого параметра (независимо от того, является ли аргумент lvalue или rvalue), который может быть оптимизирован или не оптимизирован.
Почему бы не использовать делегирование конструктора (из C++11):
MyClass(std::vector<float>&& v1, std::vector<float>&& v2) :
_v1(std::move(v1)), _v2(std::move(v2)) {};
MyClass(std::vector<float>&& v1, std::vector<float>&& v2, std::vector<float> &&v3):
MyClass(v1, v2) {
_v3 = std::move(v3);
}
Это хороший способ избежать дублирования кода. Обратите внимание, что вы не можете смешивать делегирование конструктора с инициализацией члена.
Если вам также нужен конструктор с одним вектором, вы можете переписать фрагмент кода выше:
MyClass(std::vector<float>&& v1) :
_v1(std::move(v1)){};
MyClass(std::vector<float>&& v1, std::vector<float>&& v2) :
MyClass(v1) { //
_v2 = std::move(v2);
};
MyClass(std::vector<float>&& v1, std::vector<float>&& v2, std::vector<float> &&v3):
MyClass(v1, v2) {
_v3 = std::move(v3);
};