RVO или переместить для std::список

#c #move-semantics #return-value-optimization

Вопрос:

У меня есть следующая реализация, которая возвращает последний элемент a std::list<T> и удаляет его из списка:

   std::list<T> list_;

  T ReturnAndDeleteLast( )const
  {
    T last( list_.back() );  // copy it before delete it. 
    list_.pop_back();
    return last;
  }
 

Теперь вопрос в том, когда называть это так:

  T tmp{};

 for( .... )
 {
  // do we want to delete at this iteration?
  //YES:
    tmp = ReturnAndDeleteLast();
  // do something with tmp..
 }
 

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

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

1. Вы спрашиваете, следует ли вам использовать return std::move(last); ? Если так, то нет. Все функциональные объекты локальной продолжительности автоматического хранения автоматически перемещаются, если их можно, а затем копируются, если их невозможно переместить.

2. Вы могли бы сделать T last( std::move(list_.back()) ); это для потенциальной выгоды. Конечно, загадка заключается в том, почему у вас есть const функция-член, изменяющая то, что выглядит как список участников.

3. return std::move(last); предотвратите НРВО. return last; может сделать NRVO, а в худшем случае переместиться (так как список подвижен).

4. @Рассказчик-АнсландерМоника Я думал об этом. Но я не уверен, что происходит с объектом list_.back() . Он удален? Означает ли это, что мне, например, это не нужно list_.pop_back() ?

5. Нет, семантика перемещения работает не так. У вас есть измененный объект, оставленный там в некотором разрушаемом/назначаемом состоянии. Вы хлопаете, чтобы устранить это. Но любые ресурсы, которыми он, возможно, располагал внутри страны, уже переведены на местный last уровень . Думайте о поверхностном копировании, а не о глубоком копировании, как у вас сейчас.