2016-09-17 6 views
2

Я пытался следующую программу:Почему существует разница в вызове конструкторов при передаче по значению функции и передаче по значению другому конструктору?

#include <iostream> 
using namespace std; 
class Type{ 
    int i; 
    public: 
    Type() {cout << "type constructor "<<endl;} 
    Type (const Type &) { cout << "type copy constructor called" << endl;} 
}; 

class MyClass { 
    Type variable; 
public: 
    MyClass(Type a) { 
    cout << "inside MyClass constructor "<<endl; 
    variable = a; 
    } 
}; 
void fun (Type){ 
    return; 
} 

int main(){ 
    Type t; 
    cout <<"t created"<<endl; 
    MyClass tmp = MyClass(t); 
    cout<<"calling fun"<<endl; 
    fun(t); 
} 

Выход этого:

type constructor 
t created 
type copy constructor called 
type constructor 
inside MyClass constructor 
calling fun 
type copy constructor called 

Я задаюсь вопросом, почему конструктор по умолчанию вызывается, когда я прохожу его MyClass конструктор и почему конструктор копирования называется когда я передаю его fun()?
BTW такой же бывает, когда я использую список инициализаторов.

ответ

2

Я задаюсь вопросом, почему конструктор по умолчанию вызывается, когда я передать его в конструктор MyClass

Это не имеет ничего общего с переходом аргумент здесь. В качестве переменной-члена сначала будет построено значение variable.

class MyClass { 
    Type variable; 
public: 
    MyClass(Type a) { // variable will be default constructed at first, since it's not initialized via member initializer list 
    cout << "inside MyClass constructor "<<endl; 
    variable = a;  // then variable is assgined via assignment operator 
    } 
}; 

Вы можете указать, как variable будет инициализирован списком intializer члена, как

class MyClass { 
    Type variable; 
public: 
    MyClass(Type a) : variable(a) { // variable will be direct initialized via copy constructor 
    cout << "inside MyClass constructor "<<endl; 
    // variable = a;     // no need for assignment 
    } 
}; 

конструктор по умолчанию не будет вызываться для этого случая.

+1

[pedantic] 'variable' не является копией, инициализированной из' a' там, это прямая инициализация. – Barry

0

Копировальный конструктор вызывается для обоих параметров (один для конструктора MyClass и один для fun), и журналы, которые вы опубликовали, сообщают об этом.
На самом деле, у вас есть два раза следующей строки:

типа конструктор копирование под названием

Конструктор по умолчанию вызывается для элемента данных variable, ибо он явно не инициализирован.
То же самое происходит, если вы используете список инициализатора так:

MyClass(Type a): variable{} { 
    //... 
} 

На самом деле, variable по умолчанию инициализировано, если у вас нет какого-либо списка инициализатора, так что нет никаких оснований ожидать другой журнал.