您的位置:首页 > 编程语言 > C语言/C++

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

2017-02-17 21:56 267 查看
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.用花括号列表初始化一个数组的元素或者一个聚合类(很少使用)中的成员时。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: