Почему явный вызов базового конструктора перемещения фактически вызывает базовый конструктор копирования? [дубликат]
На этот вопрос уже есть ответ здесь:
Я пытаюсь позвонить прямо на базу переместить конструктор класса через производный двигаться конструктор класса а, сюрприз!, что на самом деле вызывает базовый конструктор копирования класса не основание двигаться конструктор класса.
Я использую функцию std::move()
на объекте, чтобы быть уверенным что производные двигаться конструктор вызывается!
Код:
class Base
{
public:
Base(const Base& rhs){ cout << "base copy ctor" << endl; }
Base(Base&& rhs){ cout << "base move ctor" << endl; }
};
class Derived : public Base
{
public:
Derived(Derived&& rhs) : Base(rhs) { cout << "derived move ctor"; }
Derived(const Derived& rhs) : Base(rhs) { cout << "derived copy ctor" << endl; }
};
int main()
{
Derived a;
Derived y = std::move(a); // invoke move ctor
cin.ignore();
return 0;
}
ВЫВОД ПРОГРАММЫ:
Базовая копия ctor
Производный ход ctor
Как вы видите, базовый класс move ctor забывается, так как же его назвать?
3 ответа:
В контексте вашего класса
Derived
параметрrhs
явно имеет имя. Таким образом, это должно быть lvalue, это не может быть rvalue. ОднакоT&&
связывается только с rvalues. Если вы хотите вызвать конструктор перемещения базового класса, вам нужно использовать следующий код:Derived(Derived&& rhs): Base(std::move(rhs)) { std::cout << "derived move ctor"; }
Это вызовет конструктор перемещения
Base
и переместитBase
Частьrhs
. ПосколькуBase
ничего не знает о членахDerived
, конструкторBase
move не будет перемещать ничего, добавленноеDerived
.
Конструктор или любая другая функция или метод, имеющие
&&
в сигнатуре, могут быть выбраны компилятором только в том случае, если выполняются оба эти условия:
- Тип данных выражения, которое вы передаете, -
T&&
илиT
. - то естьT&
не будет принято- и фактически это должно быть rvalue - например, возвращаемое (по значению
T
или поT&&
) из функции.
move(rhs)
удовлетворяет обоим этим условиям.rhs
имеет право тип, но он фактически должен быть возвращен из функции (например,move
), прежде чем его можно будет считать допустимым для передачи в функцию, которая требует&&
.