Когда компилятор не может использовать RVO или 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 в хранилище, предоставляемом вызывающим абонентом. Но если компилятор достаточно умен, он может заметить, что уничтожение этого объекта является нулевой операцией. И вообще, для любого конкретного ситуация, если компилятор достаточно умен, то, возможно, ему удастся избежать операции копирования, независимо от того, насколько скрытно мы разрабатываем код.
Я не уверен в формальном, но выше, с большей полезной нагрузкой в объекте, чтобы копирование было более дорогим, является одним из случаев, когда семантика перемещения может помочь, так что оптимизация будет гарантирована независимо от умов компилятора (или нет).