Корректен ли подобный код?
template <typename smth> int f() {
smth x;
smth y = std::move(x);
smth z = std::move(x); // Снова x, не y
return y.do_smth();
}
Никакого определенного ответа на этот вопрос уровня language-lawyer
нет. Точнее, с точки зрения абстрактного языка С++ ничего необычного в этом коде нет. В языке С++ существуют разные типы ссылок (включая rvalue-ссылки), категории выражений и правила overload resolution. Если приведенный выше код корректен с точки зрения этих правил, то с точки зрения language-lawyer
в этом коде все в порядке.
А что тут будет происходить во время выполнения - зависит только от авторов класса smth
. Семантика перемещения - это чисто пользовательская концепция, которая всегда определяется только чисто пользовательским кодом, то есть реализацией класса smth
. Только от нее будет зависеть "корректность" или "некорректность" этого кода во время выполнения.
Все соглашения и гарантии, используемые при реализации семантики перемещения - это чисто "джентльменские соглашения". Языку С++ эти соглашения не известны и не интересны.
И что вообще имеется в виду под "корректен"?
Если первая инициализация физически выполнила перемещение из x
, то x
получил какое-то новое "перемещенное" состояние, допускающее как минимум корректную деструкцию x
и, по "джентльменским соглашениям", возможность присвоить x
новое значение.
Опять же, вы не обязаны соблюдать последнее соглашение: вы можете полностью запретить какое-либо дальнейшее использование объекта вашего класса после перемещения из него. И даже возможность корректной деструкции "перемещенного" объекта - это тоже не столько требование языка, сколько требование здравого смысла и структуры вашего примера.
Допускает ли "перемещенное" состояние x
повторное перемещение из x
? Что при этом получится в z
? Это определяется только реализацией smth
. И если реализация такова, что поведение этого кода полностью определено, то формально тут все совершенно корректно.
А устроит ли вас то, что y
и z
получат разные состояния и можно ли для такого y
делать y.do_smth()
- это определяют авторы класса smth
. Можно ли делать x.do_smth()
и z.do_smth()
- тоже определяют именно они.
В наиболее безопасном случае для класса smth
семантика перемещения может совпадать с семантикой копирования. Тогда этот код будет вести себя так же, как такой же код без std::move
.
В другом варианте реализации перемещение из smth
может приводить объект в обычное "пустое" состояние, как будто объект только что сконструирован конструктором по умолчанию. Тогда [наверное] объект z
тоже получит такое же "пустое" состояние.
Примеров поведения можно привести бесчисленное множество, но это лишь иллюстрирует тот факт, что происходить будет именно то, что реализовали авторы класса smth
.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть запрос, который содержит кириллические символы(думаю вся проблема в них)
Уже задавал такой вопрос, но ответа нет: не обрабатывается событие KeyDownВот сам обработчик:
Есть generic-метод для преобразования типов, для всех типов в принципе он работает адекватно: