Какая структура функций лучше? - PullRequest
1 голос
/ 26 октября 2011

Посмотрите на следующий код:

class MyClass{
public:
    MyClass(){}
    MyClass(MyClass &&){}
    MyClass(const MyClass &){}
};
MyClass f1(){
    MyClass &&o=MyClass();
    /*...*/
    return std::move(o);//or return static_cast<MyClass &&>(o);
}
MyClass f2(){
    MyClass o=MyClass();
    /*...*/
    return o;
}


int main(int, char **){
    auto a=f1();
    auto b=f2();
}

Функция f2 - это нормальная форма возврата объекта. NRVO может применяться, и можно избежать дополнительного вызова конструктора копирования. f1 - это новая форма, использующая ссылку rvalue. Для систем, которые не поддерживают NRVO, но поддерживают ссылку на значение rvalue, вызывается конструктор перемещения, а не конструктор копирования, что в большинстве случаев будет лучше.

Проблема f1 заключается в следующем: существуют ли компиляторы, поддерживающие NRVO в этом случае? В конце концов, это, похоже, лучшая форма в будущем.

Ответы [ 2 ]

4 голосов
/ 26 октября 2011

есть ли в этом случае поддержка компилятора NRVO?

Определить "поддержку компилятора"?

Что f1 делает полностью уничтожить способность компилятора оптимизировать копию MyClass.Давайте рассмотрим f1 подробно

MyClass &&o=MyClass();

Это создаст временную , а не переменную стека.Затем этот временный объект привязывается к ссылке на r-значение, называемой o, которая продлевает время существования временного элемента до конца функции.

return std::move(o); //or return static_cast<MyClass &&>(o);

Возвращает ссылку на r-значение для стека.привязанная r-величина ссылается на временную.И поскольку вы возвращаете значение, а не ссылку, компилятор должен создать из него временное значение.

Копирование / перемещение временного значения в a будет исключено.Но вы все еще создали два временных (оригинал и возвращаемое значение).

Итак, f1 делает следующее:

create temporary
copy/move from temporary to return value
elide copy/move from return value to `a`.

f2 делает:

create stack variable
elide copy/move from stack variable to `b`.

Если NVRO не существует, у вас есть:

create stack variable
copy/move from stack variable to return value
elide copy/move from stack variable to `b`.

Итак, f2 равно в худшем случае равно f1.И, скорее всего, лучше.

Пожалуйста, перестаньте пытаться перехитрить компилятор.Просто позвольте копии elision делать свое дело.

2 голосов
/ 26 октября 2011

Вот как работают текущие компиляторы (магистраль MSVC10 / gcc):
Предполагая, что MyClass является подвижным

f1 : move   
f2 :   
worst case : move 
best case : NRVO 

Предполагается, что MyClass не может быть перемещен:

f1 : copy    
f2 :    
worst case : copy    
best case : NRVO 

Таким образом, даже если компиляторы поправляются и начинают выполнять NRVO для функций, подобных f1, зачем усложнять код, если классические функции C ++ 03 для f2 уже оптимальны?

...