Когда компилятор не может использовать RVO или NRVO?

семантика перемещения может быть полезна, когда компилятор не может использовать РВО и NRVO. Но в этом случае компилятор не может использовать эти функции?

2 ответов


ответ заключается в том, что он зависит от компилятора и ситуации. Е. Г. ветвление потока управления может запутать оптимизаторов. Википедия привожу этот пример:

#include <string>
std::string f(bool cond = false) {
  std::string first("first");
  std::string second("second");
  // the function may return one of two named objects
  // depending on its argument. RVO might not be applied
  return cond ? first : second;
}

int main() {
  std::string result = f();
}

Ну, дело не столько в том, может ли компилятор использовать RVO, но может ли он таким образом избежать создания копии.

считаем:

struct Blah
{
    int x;
    Blah( int const _x ): x( _x ) { cout << "Hum de dum " << x << endl; }
};

Blah foo()
{
    Blah const a( 1 );
    if( fermatWasRight() ) { return Blah( 2 ); }
    return a;
}

получение побочных эффектов (вывод из конструктора) прямо здесь, на первый взгляд довольно несовместимо с построением a directy в хранилище, предоставляемом вызывающим абонентом. Но если компилятор достаточно умен, он может заметить, что уничтожение этого объекта является нулевой операцией. И вообще, для любого конкретного ситуация, если компилятор достаточно умен, то, возможно, ему удастся избежать операции копирования, независимо от того, насколько скрытно мы разрабатываем код.

Я не уверен в формальном, но выше, с большей полезной нагрузкой в объекте, чтобы копирование было более дорогим, является одним из случаев, когда семантика перемещения может помочь, так что оптимизация будет гарантирована независимо от умов компилятора (или нет).