c++之拷贝构造函数调用时机

test1:

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "这是有默认参数的构造函数!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "这是拷贝构造函数!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一个对象被析构了!\n";
18     }
19 private:
20     int a;
21 };
22 void fuc(Copy_construction t)
23 {
24     cout << "fuc函数!\n";
25 }
26 void play_empty(void)
27 {
28     Copy_construction t1;//调用有默认实参的构造函数
29     Copy_construction t2 = t1;//调用拷贝构造函数
30     Copy_construction t3(t2);//调用拷贝构造函数
31     cout << "_________________\n";
32     fuc(t3);//实参初始化形参,调用拷贝构造函数
33 }
34 int main()
35 {
36     play_empty();
37 
38     cout << "hello world!\n";
39     return 0;
40 }
View Code

运行结果

 test2:

修改fuc函数为引用或者指针类型。

 

 1 void fuc(Copy_construction *t)
 2 {
 3     cout << "fuc函数!\n";
 4 }
 5 
 6 
 7 void fuc(Copy_construction &t)
 8 {
 9     cout << "fuc函数!\n";
10 }
11 
12 /*****引用或者指针类型调用时不会调用拷贝构造函数****/

test3:

匿名对象的出现:

 

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "这是有默认参数的构造函数!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "这是拷贝构造函数!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一个对象被析构了!\n";
18     }
19 private:
20     int a;
21 };
22 Copy_construction fuc(void)
23 {
24     cout << "fuc函数!\n";
25     Copy_construction A;
26     return A;//调用拷贝构造函数,生成匿名对象
27 }//运行到该处,先析构对象A,匿名对象是否析构要看怎么去接
28 //如下所示直接调用fuc()则此时匿名对象会被立即析构
29 void play_empty(void)
30 {
31     fuc();
32 }
33 int main()
34 {
35     play_empty();
36 
37     cout << "hello world!\n";
38     return 0;
39 }

如果直接显示调用构造函数,要看怎么去接这个函数, Copy_construction(1);调用之后马上执行析构匿名对象 Copy_construction  T= Copy_construction(1);不会马上析构还会转正

test4:

修改fuc函数的返回类型为引用或者指针:

 

 1 Copy_construction *fuc(void)
 2 {
 3     cout << "fuc函数!\n";
 4     Copy_construction A;
 5     return &A;
 6 }
 7 
 8 Copy_construction &fuc(void)
 9 {
10     cout << "fuc函数!\n";
11     Copy_construction A;
12     return A;
13 }
14 
15 
16 /********返回类型为指针或者引用不会调用拷贝构造函数*********/

test5:

改变接匿名对象的方式:

 

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "这是有默认参数的构造函数!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "这是拷贝构造函数!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一个对象被析构了!\n";
18     }
19 private:
20     int a;
21 };
22 Copy_construction fuc(void)
23 {
24     cout << "fuc函数!\n";
25     Copy_construction A;
26     return A;//调用拷贝构造函数,产生匿名对象
27 }//析构对象A,根据下面代码的接匿名对象的方式,
28 //此时匿名对象不仅不会马上析构,还会转正成为对象B
29 //从c++设计哲学上来说,这也是提高效率的一种方式,这样的设计是合理的,因为你想创建对象B,我就不用再新开辟内存了,直接用之前的匿名对象代替
30 void play_empty(void)
31 {
32     Copy_construction B=fuc();//这里不会调用拷贝构造函数,匿名对象直接转正了
33     cout << "匿名对象转正!\n";
34 }
35 int main()
36 {
37     play_empty();
38 
39     cout << "hello world!\n";
40     return 0;
41 }

test6:

再改变接匿名对象的方式,重写play_empty()函数:

 

void play_empty(void)
{
    Copy_construction B;
    B= fuc();
    cout << "匿名对象不会转正!\n";
}


//如上所示代码,此时对象B会开辟内存,在用返回的匿名对象赋值给B,将会在赋值完成之后立即析构匿名对象,这个时候匿名对象不会转正。

summary:以下情况会调用拷贝构造函数

1.直接初始化和拷贝初始化时

2.将一个对象作为实参传递给一个非引用或非指针类型的形参时

3.从一个返回类型为非引用或非指针的函数返回一个对象时

4.用花括号列表初始化一个数组的元素或者一个聚合类(很少使用)中的成员时。

 

posted @ 2017-02-17 21:56  Crystal_Guang  阅读(3342)  评论(0编辑  收藏