Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.117.81.240] |
|
Сообщ.
#1
,
|
|
|
Наткнулся тут на некий код
std::vector<Something> items; ... items = call_come_func(std::move(items)); Это UB или нет? С одной стороны, похоже на x = std::move(x), которое UB, с другой тут вроде как точка следования (или как это называется в новых стандартах). Непонятно. |
Сообщ.
#2
,
|
|
|
Если call_come_func() действительно функция, то да, перед её вызовом и после её возврата есть точки следования. Даже если та встраивается.
Цитата OpenGL @ Это не UB. Вообще говоря, такая конструкция законна, но результат зависит от x. Не отличается от присваивания самому себе, в общем-то. Правильно реализованное присваивание не нуждается ни в каких if (this == &lhs) в своей реализации, окромя как с целью оптимизации. С перемещающим присваиванием тот же принцип. Другое дело, что с целью оптимизации её зачастую не учитывают, потому что иначе просто пропадает смысл использовать перемещение вместо копирования. x = std::move(x), которое UB |
Сообщ.
#3
,
|
|
|
Цитата Qraizer @ Это не UB. Хм. Странно, где-то видел, что это UB, а сейчас найти не могу Ок, тогда и исходная конструкция не UB, получается. Цитата Qraizer @ Если call_come_func() действительно функция, то да, перед её вызовом и после её возврата есть точки следования. А какая разница? Если это не функция, а объект, то один фиг позовётся operator(), т.е. это та же функция, разве нет? Или ты имеешь ввиду, что если там какой-нибудь пустой define call_come_func, то точки следования уже не будет, т.к. это будет просто скобками? |
Сообщ.
#4
,
|
|
|
Ну, это ведь мог быть макрос... Или тип, получилось как будто бы items = (call_come_func)std::move(items); За точки следования Стандарт говорит в контексте функций. А так-то да, методы тоже функции. И да: каст конструктором – это тоже функция. Но call_come_func может быть каким-нибудь typedef-ом от, скажем, int (&)[123] или там поинтера на функцию, а такие касты уже совсем не функции.
Цитата OpenGL @ Я тут подумал... возможно, там, где ты читал, имелось в виду, что если аргумент перемещающего присваивания по факту является lvalue, которое подвергнуто касту к rvalue ref, в частности посредством std::move(), то, т.к. перемещающие присваивания – та и конструкторы тоже – имеют полное право полагать, что rvalue источник программисту больше не нужен, они могут с источником делать "странные вещи". И когда это накладывается на то, что приёмником является этот же самый аргумент, это может повлечь неожиданные эффекты. Ну... я примерно это и сказал. При том, что ещё упомянул, что и с обычным присваиванием подобная байда легко может случиться, если его реализовать криво. При такой постановке вопроса – да, невозможно гарантировать корректность присваиваний самому себе, но это справедливо для обоих типов присваивания. А так-то я вот не вижу причин, почему бы вектору не переместить самого себя в себя. Все те std::swap(), посредством которых вектор перемещается очень эффективно, по идее вообще должны будут соптимизироваться просто в nop. Странно, где-то видел, что это UB, а сейчас найти не могу |