Особенности работы RVO и NRVO

126
18 сентября 2019, 02:40
#include <iostream>
class A
{
  int x;
  public:
  A(int x):x(x){std::cout<<"A():"<<this<<'\n';}
  A(const A&other){std::cout<<"A(const&):"<<this<<'\n';}
  A(A&&other){std::cout<<"A(const&&):"<<this<<'\n';}
  ~A(){std::cout<<"~A():"<<this<<'\n';}
};
A createObject_NRVO(int param)
{
    std::cout<<"create Object (NRVO) "<<'\n';
    A a1(1), a2(2);
    if(param > 10)
    return a1;
    else
    return a2;
}
A createObject_RVO(int param)
{
    std::cout<<"create Object (RVO) "<<'\n';
    if(param > 10)
    return A(1);
    else
    return A(2);
}
int main() {
    A a = createObject_NRVO(1);
    //A a2 = createObject_RVO(1);
}

Вызываем createObject_NRVO(1) получаем:

create Object (NRVO)

A():0x7ffd83d94ec0

A():0x7ffd83d94ec4

A(const&&):0x7ffd83d94ef4

~A():0x7ffd83d94ec4

~A():0x7ffd83d94ec0

~A():0x7ffd83d94ef4

Вызываем createObject_RVO(1) получаем:

create Object (RVO)

A():0x7ffdb5323d84

~A():0x7ffdb5323d84

Почему RVO срабатывает, а NRVO нет?

Answer 1

Дело в том, что при NRVO компилятор может опускать только конструктор копирования, создавая объект сразу по месту вызова, при этом объекты и a1, и a2 он создать обязан, но не может заранее определить, какой из этих временных объектов должен создаваться на месте возвращаемого значения.

Проще говоря, чтобы NRVO работала во всех ветвях функции должен возвращаться один и тот же объект. Рабочий вариант будет выглядеть например так:

#include <iostream>
class A
{
  int x;
  public:
  A(){std::cout<<"A():"<<this<<'\n';}
  A(int x):x(x){std::cout<<"A(int):"<<this<<'\n';}
  A(const A&other){std::cout<<"A(const&):"<<this<<'\n';}
  A(A&&other){std::cout<<"A(const&&):"<<this<<'\n';}
  ~A(){std::cout<<"~A():"<<this<<'\n';}
  setX(int _x){x=_x;std::cout<<"A::setX():"<<this<<'\n';}
};
A createObject_NRVO(int param)
{
    std::cout<<"create Object (NRVO) "<<'\n';
    int 
    A a;
    if(param > 10) {
      a.setX(1);
    } else {
      a.setX(2);
    }
    return a;
}
READ ALSO
Выдать пять не повторяющихся карт

Выдать пять не повторяющихся карт

Условие задачиДана колода из 52 карт

117
C++ Создать экземпляр класса, используя заданный размер динамической памяти

C++ Создать экземпляр класса, используя заданный размер динамической памяти

Нужно создать экземпляр класса, используя заданный размер динамической памятиПробовал прописать вот так Stroka *stroka = new Stroka[10];, но появляется...

119
Насколько сейчас актуально WinAPI? [закрыт]

Насколько сейчас актуально WinAPI? [закрыт]

Изучаю разработку программ на C++ по книгамТам для создания окон и многого другого используется библиотека WinAPI

107