Есть ли какой-либо способ вызвать оператор присваивания перемещения в C без std::move?

#c #c 11 #c 14 #c 17

#c #c 11 #c 14 #c 17

Вопрос:

Интересно, можно ли вызвать оператор присваивания перемещения без использования стандартной библиотеки std::move .

Так, например, если я вызываю :

 class A {
    private:
        char* data;
    public:
        // move constructor
        A(Aamp;amp; other) : data(other.data) {
            // we steal the pointer!
            other.data = NULL;
        }
        // move operator=
        Aamp; operator=(Aamp;amp; other) {
            if (this != amp;other) {
                delete data;
                data = other.data;
                data.foo = NULL;
        }
            return *this;
        }
};

int main(){
    A objA; 
    A objB; 
    objB = std::move(objA);
}


 

могу ли я теперь написать что-то другое, кроме objB = std::move(objA); ?

Комментарии:

1. Вы можете objB = A(); переназначить из вновь созданного неназванного значения. Аналогично, вы могли бы назначить результат функции, которая возвращает A . Но в остальном вы используете std::move или реализуете свою собственную эквивалентную функцию или приведение; немного неясно, почему вы хотите это сделать; можете ли вы указать причину , чтобы мы могли ответить более эффективно?

2. Ваш вопрос достаточно ясен, но, пожалуйста, постарайтесь сделать ваш пример воспроизводимым. У вас нет конструктора по умолчанию, поэтому код main не компилируется. Кроме того, что такое data.foo ?

3. Не связано: начиная с C 14, есть отличная маленькая функция, std::exchange которую вы могли бы использовать в своем конструкторе перемещения, чтобы сделать это A(Aamp;amp; other) : data(std::exchange(other.data, nullptr)) {}

4. Что data.foo = NULL; предполагается делать? Вы имели в виду other.data = nullptr; ?

5. Добавьте функцию-член Aamp;amp; operator () { return static_cast<Aamp;amp;>(*this); } , тогда вы сможете это сделать objB = objA; . Жаль, что в C нет унарного operatoramp;amp; .

Ответ №1:

Есть ли какой-либо способ вызвать оператор присваивания перемещения в C без std::move?

std::move это очень простая функция, которая просто выполняет приведение. Вы можете написать это приведение вместо вызова функции:

 objB = static_cast<Aamp;amp;>(objA);
 

Я не знаю практической причины для этого.

Комментарии:

1. Просто чтобы избежать путаницы: это приведение здесь работает нормально, но фактическая реализация std::move немного более тонкая, чтобы иметь дело с вызовом его по ссылке. 1.

2. @PeteBecker Только потому, что аргумент шаблона [обычно] выводится; показанный код действительно эквивалентен вызову to std::move(objA) , потому что мы явно указываем аргумент for static_cast . Если вы создали его по шаблону, то да, вам тоже нужно было бы remove_reference . То же самое, если вы попытались static_cast<decltype(objA)>(objA) по какой-то причине.

Ответ №2:

Предполагая, что вы хотите сохранить objA как именованную локальную переменную, тогда нет, нет способа передать ее конструктору objB и заставить вызываемый конструктор быть конструктором перемещения, за исключением использования std::move (или эквивалентных вещей, которые аналогичным образом возвращаются Tamp;amp; , чтобы выражение было значением rvalue T , например a static_cast<Aamp;amp;> ).

Это сделано специально. Не должно быть возможности случайно перейти от именованного объявленного объекта; вам нужно будет попросить об этом. Вот почему std::move вызывается std::move , несмотря на то, что сам по себе не выполняет никакого перемещения: его имя четко указывает на обычное намерение его использовать.

Другой способ вызвать конструктор перемещения — передать выражение, которое изначально никогда не будет значением lvalue , например, такое, которое создает временное.