Return value optimization в C++

Век живи, век учись... Сегодня мне пришлось столкнуться с вещью, о которой я раньше не знал. Не буду мучать читателя рассказами, а покажу сразу на примере. Допустим, есть следующий код.

#include <iostream>

// наш класс
class A
{
    public:
        A() { std::cout << "A()" << std::endl; }
        A(const A& rhs) { std::cout << "A(const A&)" << std::endl; }
        ~A() { std::cout << "~A()" << std::endl; }

        /* некоторые свойства и методы */
};

// функция, возвращающая объект нашего класса
A foo()
{
    A a;
    // некоторые действия с классом
    return a;
}

// без комментариев :)
int main(int argc, char* argv[])
{
    {
        A obj(foo());
    }

    std::cout << "The End" << std::endl;
    return 0;
}

Раньше я думал, что в функции foo() используется конструктор без параметров, а в функции main() используется конструктор копий. То есть, я ожидал следующий вывод:

A()
A(const A&)
~A()
~A()
The End

Но на деле оказалось все иначе. Вывод несколько удивил меня:

A()
~A()
The End

Очевидно, создание временного объекта и его разрушение не произошло.

Оказывается, все дело в так называемом RVO (Return value optimization). О том, что такое RVO, можно почитать на википедии. Я лишь отмечу главные моменты:

  • если на возвращаемый объект влияет некоторое внешние условие (например, передаваемый аргумент), то RVO может не сработать;
  • RVO поддерживается почти всеми основными C++ компиляторами;
  • RVO не является частью стандарта (ну это очевидно), но стандарт разрешает выполнять компилятору любые оптимизации до тех пор, пока создаваемые исполняемые файлы ведут себя так, как будто все требования стандарта выполнены;
  • поддержкой RVO можно управлять, передавая соответствующие ключи компилятору.

Note

В стандарте C++11 появился механизм под названием Movement Semantic, и путать его с RVO не стоит. Что интересно, несмотря на семантику перемещения, RVO продолжает работать и в C++11 совместимых компиляторах. Связано это, скорее всего, с тем, что RVO позволяет добиться большей производительности.