2015-09-05 3 views
0

Для следующего кода, Копировать конструктор, вызываемый дважды Почему?Зачем копировать конструктор, вызывается дважды

#include <iostream> 
using namespace std; 
class A { 
    int X; 
public: 
    A() { 
     cout << "Simple Constructor" << endl; 
    } 
    A(int b) :X(b) { 
     cout << "Constructor " << X << endl; 
    } 
    A(const A& obj) :X(obj.X) { 
     cout << "Copy Constructor " << endl; 
    } 
    ~A() { 
     cout << "Destructor " << X << endl; 
    } 
}; 
A fun(A obj) { 
    cout << "Fun" << endl; 
    return obj; 
} 
int main() { 
    A obj(10); 
    obj = fun(obj); // here is confusion 
    cout << "End" << endl; 
    return 0; 
} 

Выход:

Constructor 10 
Copy Constructor 
Fun 
Copy Constructor 
Destructor 10 
Destructor 10 
End 
Destructor 10 

Я ожидаю, что может быть второй Конструктор копирования Из-за временного объекта. что ты говоришь?

+0

В 'fun()' вы берете копию и возвращаете копию, так почему вы задаетесь вопросом? –

+0

@ πάνταῥεῖ возвращаемый объект, скопированный на временный объект? а затем объект объекта и временный объект уничтожаются? –

+0

Как видите, да. –

ответ

1

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

Я не знаю, каковы ваши намерения. Если вы хотите изменить объект в функцию, было бы лучше, чтобы передать его по ссылке и сделать функцию пустоту:

void fun(A& obj) { 
    cout << "Fun" << endl; 
} 

и просто позвоните

fun(obj); 

Таким образом, можно предотвратить и вызовы конструктора копии ,

Edit:

Если вам интересно, почему Возвращаемое значение Оптимизация не выполняется, вы должны знать, что это не является обязательным поведением, что разрешено для компилятора по стандарту. Сначала вы должны убедиться, что вашему компилятору разрешено оптимизировать код (например, вы не используете Debug Build), а затем, что он действительно поддерживает RVO. Наконец, вы должны подумать, действительно ли оптимизация имеет смысл в этом случае. У вашего объекта есть только один int внутри, поэтому он имеет размер базового типа. Одна вещь, которую следует помнить об оптимизации, заключается в том, что она МОЖЕТ быть выполнена, но компилятор - это тот, который решает, выполнять или нет.

+0

, но 2-й экземпляр, скопированный во временный объект? –

+0

Скопирован из obj (в оператор return) во временный объект, а затем вызывается оператор присваивания по умолчанию (в obj = fun ...), который принимает значение const в качестве аргумента. – Estiny