На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> UB или нет
    Наткнулся тут на некий код

    ExpandedWrap disabled
      std::vector<Something> items;
      ...
      items = call_come_func(std::move(items));

    Это UB или нет? С одной стороны, похоже на x = std::move(x), которое UB, с другой тут вроде как точка следования (или как это называется в новых стандартах). Непонятно.
      Если call_come_func() действительно функция, то да, перед её вызовом и после её возврата есть точки следования. Даже если та встраивается.
      Цитата OpenGL @
      x = std::move(x), которое UB
      Это не UB. Вообще говоря, такая конструкция законна, но результат зависит от x. Не отличается от присваивания самому себе, в общем-то. Правильно реализованное присваивание не нуждается ни в каких if (this == &lhs) в своей реализации, окромя как с целью оптимизации. С перемещающим присваиванием тот же принцип. Другое дело, что с целью оптимизации её зачастую не учитывают, потому что иначе просто пропадает смысл использовать перемещение вместо копирования.
        Цитата Qraizer @
        Это не UB.

        Хм. Странно, где-то видел, что это UB, а сейчас найти не могу :D Ок, тогда и исходная конструкция не UB, получается.

        Цитата Qraizer @
        Если call_come_func() действительно функция, то да, перед её вызовом и после её возврата есть точки следования.

        А какая разница? Если это не функция, а объект, то один фиг позовётся operator(), т.е. это та же функция, разве нет? Или ты имеешь ввиду, что если там какой-нибудь пустой define call_come_func, то точки следования уже не будет, т.к. это будет просто скобками?
          Ну, это ведь мог быть макрос... Или тип, получилось как будто бы items = (call_come_func)std::move(items); За точки следования Стандарт говорит в контексте функций. А так-то да, методы тоже функции. И да: каст конструктором – это тоже функция. Но call_come_func может быть каким-нибудь typedef-ом от, скажем, int (&)[123] или там поинтера на функцию, а такие касты уже совсем не функции.
          Цитата OpenGL @
          Странно, где-то видел, что это UB, а сейчас найти не могу
          Я тут подумал... возможно, там, где ты читал, имелось в виду, что если аргумент перемещающего присваивания по факту является lvalue, которое подвергнуто касту к rvalue ref, в частности посредством std::move(), то, т.к. перемещающие присваивания – та и конструкторы тоже – имеют полное право полагать, что rvalue источник программисту больше не нужен, они могут с источником делать "странные вещи". И когда это накладывается на то, что приёмником является этот же самый аргумент, это может повлечь неожиданные эффекты. Ну... я примерно это и сказал. При том, что ещё упомянул, что и с обычным присваиванием подобная байда легко может случиться, если его реализовать криво. При такой постановке вопроса – да, невозможно гарантировать корректность присваиваний самому себе, но это справедливо для обоих типов присваивания. А так-то я вот не вижу причин, почему бы вектору не переместить самого себя в себя. Все те std::swap(), посредством которых вектор перемещается очень эффективно, по идее вообще должны будут соптимизироваться просто в nop.
          Сообщение отредактировано: Qraizer -
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,0216 ]   [ 16 queries used ]   [ Generated: 28.03.24, 17:27 GMT ]