Переместить конструктор на производном объекте
Когда у вас есть производный объект с конструктором перемещения, а базовый объект также имеет семантику перемещения, каков правильный способ вызова конструктора перемещения базового объекта из конструктора перемещения производного объекта?
Сначала я попытался сделать самое очевидное:
Derived(Derived&& rval) : Base(rval)
{ }
Однако, похоже, это вызывает вызов конструктора копии базового объекта. Затем я попытался явно использовать std::move
здесь, например:
Derived(Derived&& rval) : Base(std::move(rval))
{ }
Это сработало, но я смущен, почему это необходимо. Я думал, что std::move
просто возвращает ссылку rvalue. Но так как в этом примере rval
уже является ссылкой rvalue, вызов std::move
должен быть лишним. Но если я не использую std::move
здесь, он просто вызывает конструктор копирования. Итак, почему нужен вызов std::move
?
Ответы
Ответ 1
rval не является Rvalue. Это Lvalue внутри тела конструктора перемещения. Вот почему мы должны явно ссылаться на std:: move.
Обратитесь к этому. Важно отметить
Обратите внимание, что аргумент x равен рассматривается как внутреннее значение lvalue перемещать функции, даже если это объявлен как ссылка rvalue параметр. Вот почему это необходимо сказать move (x) вместо просто x, когда переходя к базовому классу. Эта является ключевой функцией безопасности перемещения семантика, предназначенная для предотвращения случайно двигаясь дважды с некоторых именованная переменная. Все перемещения происходят только из rvalues или с явным литом rvalue, например, используя std:: move. Если у вас есть имя для переменной, это является lvalue.
Ответ 2
Вам действительно нужно использовать std:: forward (obj), а не std:: move (obj). Forward вернет правильное значение rvalue или lvalue, основанное на том, что obj, тогда как перемещение превратит lvalue в rvalue.