Информация об изменениях

Сообщение Re: Как правильно вызывать мув ctor и мув operator= базового от 01.12.2023 19:47

Изменено 01.12.2023 20:12 rg45

Re: Как правильно вызывать мув ctor и мув operator= базового
Здравствуйте, Marty, Вы писали:

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).

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&&)
};