#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)
, потому что мы явно указываем аргумент forstatic_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 , например, такое, которое создает временное.