Сообщение Re: Как правильно вызывать мув ctor и мув operator= базового от 01.12.2023 19:47
Изменено 01.12.2023 20:11 rg45
Re: Как правильно вызывать мув ctor и мув operator= базового
Здравствуйте, Marty, Вы писали:
M>Просто вызвать, как обычный конструктор копирования/operator=, присунуть туда при вызове std::move, или ещё что-то?
Конечно нужно присунуть move. Фишка в том, что внутри конструктора, фактический параметр, пришедший по rvalue ссылке, превращается в lvalue выражение, и без move, в лучшем случае, возникнет ошибка компиляции, а в худшем — вызовется не тот конструктор (копирование вместо перемещения).
И для чистоты можно даже вместо move использовать forward для того, чтоб сразу привести аргумент к базовому классу — во избежание разного рода сюрпризов (мало ли, вдруг, в базовом классе объявлен шаблонный конструктор, принимающий perfect forwarding reference).
M>Просто вызвать, как обычный конструктор копирования/operator=, присунуть туда при вызове std::move, или ещё что-то?
Конечно нужно присунуть move. Фишка в том, что внутри конструктора, фактический параметр, пришедший по rvalue ссылке, превращается в lvalue выражение, и без move, в лучшем случае, возникнет ошибка компиляции, а в худшем — вызовется не тот конструктор (копирование вместо перемещения).
И для чистоты можно даже вместо move использовать forward для того, чтоб сразу привести аргумент к базовому классу — во избежание разного рода сюрпризов (мало ли, вдруг, в базовом классе объявлен шаблонный конструктор, принимающий perfect forwarding reference).
struct Base
{
Base() = default;
Base(Base&&) = default;
template <typename T>
Base(T&&);
};
struct Derived : Base
{
Derived() = default;
Derived(Derived&& rhs) : Base(std::forward<Base>(rhs)) {} // Будет использован Base(Base&&)
// При замене forward на move
// будет использован шаблонный Base(T&&)
};
Re: Как правильно вызывать мув ctor и мув operator= базового
Здравствуйте, Marty, Вы писали:
M>Просто вызвать, как обычный конструктор копирования/operator=, присунуть туда при вызове std::move, или ещё что-то?
Конечно нужно присунуть move. Фишка в том, что внутри конструктора фактический параметр, пришедший по rvalue ссылке, превращается в lvalue выражение, и без move, в лучшем случае, возникнет ошибка компиляции, а в худшем — вызовется не тот конструктор (копирование вместо перемещения).
И для чистоты можно даже вместо move использовать forward для того, чтоб сразу привести аргумент к базовому классу — во избежание разного рода сюрпризов (мало ли, вдруг, в базовом классе объявлен шаблонный конструктор, принимающий perfect forwarding reference).
M>Просто вызвать, как обычный конструктор копирования/operator=, присунуть туда при вызове std::move, или ещё что-то?
Конечно нужно присунуть move. Фишка в том, что внутри конструктора фактический параметр, пришедший по rvalue ссылке, превращается в lvalue выражение, и без move, в лучшем случае, возникнет ошибка компиляции, а в худшем — вызовется не тот конструктор (копирование вместо перемещения).
И для чистоты можно даже вместо move использовать forward для того, чтоб сразу привести аргумент к базовому классу — во избежание разного рода сюрпризов (мало ли, вдруг, в базовом классе объявлен шаблонный конструктор, принимающий perfect forwarding reference).
struct Base
{
Base() = default;
Base(Base&&) = default;
template <typename T>
Base(T&&);
};
struct Derived : Base
{
Derived() = default;
Derived(Derived&& rhs) : Base(std::forward<Base>(rhs)) {} // Будет использован Base(Base&&)
// При замене forward на move
// будет использован шаблонный Base(T&&)
};