2016-07-14 4 views
-1

Существует класс Complex с конструктором, который печатает сообщение для RVO.
Я тестировал метод оператора + метод в gtest.
Если произошел RVO, печатает "Complex !!" сообщений в 3 раза.
Но есть «Комплекс!» сообщений в 5 раз.
RVO не было, думаю.
Я скомпилировал этот код с помощью C++ 98 и C++ 11
Почему RVO не возникает?
Почему RVO не применяется в этом коде

#include <stdio.h> 

class Complex { 
    friend Complex operator+(const Complex&, const Complex&); 
public: 
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { printf("\nComplex!!\n");} 

    Complex(const Complex& c) : real(c.real), imag(c.imag) {} 

    Complex& operator=(const Complex& c) { 
     real = c.real; 
     imag = c.imag; 

     return *this; 
    } 

    ~Complex() {} 
private: 
    double real; 
    double imag; 
}; 

Complex operator+(const Complex& lhs, const Complex& rhs) 
{ 
    return Complex(lhs.real + rhs.real, lhs.imag + rhs.imag); 
} 

int main() 
{ 
    Complex a(1.0), b(2.0), c; 

    for (int i = 0; i < 2; i++) { 
     c = a + b; 
    } 
} 
+6

Существует 5 вызовов конструктора: по одному для инициализации 'a',' b' и 'c' и по одному для каждого вызова' operator + '. Почему вы думаете, что будет какой-то другой номер? Какие из них, по вашему мнению, не должны произойти? – immibis

+3

RVO elides вызывает копирование конструкторов и перемещение конструкторов, а не других. Поэтому ваш код ничего не говорит о RVO. –

+1

Это может произойти для 'Complex c = a + b;'. Теперь у вас есть задание, которое неприменимо. –

ответ

7

RVO не является оптимизацией для предотвращения образования объектов - это оптимизация, чтобы избежать ненужных дополнительных копий или перемещений.

Ваш пример строит три объекта (a, b и c), а затем построить еще два (a+b два раза в цикле). Эти объекты все должны быть построены, нет никакого способа, чтобы оптимизировать вокруг этого - компилятор не может развалится Complex() временной инициализации в operator+ и распаковать его в присвоения real и imag в operator=.

Если вы измерили свою копию и переместите конструктор, вы увидите, что они не вызывались в вашем примере. Но они могли быть. Временное созданное в пределах operator+() концептуально перемещается в возврат функции до привязки к ссылке в Complex::operator=(). Это , что переместить это через RVO, и это тот ход, который вы увидите, если вы скомпилированы с -fno-elide-constructors.

+0

Я хочу удалить временную созданную внутри оператора +(). В этом случае, как я могу удалить это временное использование с помощью RVO? –

+0

@GyeongWonDo Это не то, что вам нужно * сделать *. Если вы написали «Complex d = a + b;», который не выполнил бы copy/move, он построил бы временное место в 'd'. Но 'operator +()' должен построить объект. – Barry

+0

Я проверил, что конструктор копирования вызывается с параметром -fno-elide-constructors. Но конструктор Copy не вызывается без параметров -fno-elide-constructors. Вы имеете в виду, что это RVO? –

7

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

Вы можете проверить, было ли применено RVO, наблюдая за побочными эффектами копии и конструктором перемещения.

Ваш конструктор копирования не имеет побочных эффектов, поэтому невозможно проверить, было ли RVO применено или не было применено.

При возникновении RVO два «комплекса!» сообщения при вызове оператора + не должны печататься.

№ Эти сообщения печатаются в обычном (не копирующем) конструкторе класса. RVO не влияет на то, сколько раз вызывается обычный конструктор.

+0

Спасибо, я пишу несколько сообщений (побочных эффектов) в конструкторе копирования. И я проверил, что конструктор копирования вызван или не вызван с использованием опции -fno-elide-constructors. –

Смежные вопросы