学习拷贝构造函数和赋值运算符

时间:2021-01-03 01:36:48

拷贝构造函数在下面三种情况下被调用:

  1. 拷贝初始化,如:A b(a);
  2. 赋值初始化:如:A b = a;
  3. 函数传形参:如:foo(A a)

赋值运算只有一种情况会被调用:

  1. 非初始化的赋值:如:A b; b = a;

代码:

 1 #include <stdlib.h>
 2 #include <string>
 3 
 4 /***
 5 * @author:zanzan101
 6 */
 7 
 8 inline void P(const char* str)
 9 {
10     printf("%s\n", str);
11 }
12 
13 class A
14 {
15 private: 
16     int _data;
17     char* _name;
18 public:
19     A(): _name(0)
20     {
21         P("调用构造函数");
22     }
23 
24     // 拷贝构造函数
25     // 无论构造函数还是拷贝构造函数,都要处理好对于指针的初始化,一般,应该一开始就对指针赋值为0,后面再进一步赋值
26     // 对象的产生,究其根源只有两个途径:构造和拷贝构造,赋值运算的右值也是来自这两种途径
27     A(A& a)
28     {
29         P("调用拷贝构造函数");
30         _name = 0;
31         _data = a._data;
32         if(a._name)
33         {
34             _name = new char[strlen(a._name)+1];
35             strcpy(_name, a._name);
36         }
37     }
38 
39     // 赋值运算符
40     // 注意:返回值类型设为A&是为了实现a=b=c、(a=b)=c等操作
41     A& operator= (A& a)
42     {
43         P("调用赋值运算符");
44 
45         if(this == &a)
46             return *this;
47 
48         // 调用赋值运算的对象,必然已经经历过了构造或者拷贝构造
49         // 因此,合理的设计构造和拷贝构造函数,会使_name为0或者其他有效值,不会出现0xCCCCCCCC的非法情况
50         if(_name)
51             delete _name;
52 
53         _data = a._data;
54 
55         if(!a._name)
56             _name = 0;
57         else
58         {
59             _name = new char[strlen(a._name)+1];
60             strcpy(_name, a._name);
61         }
62         return *this;
63     }
64 };
65 
66 void foo(A a)
67 {
68     return;
69 }
70 int _tmain(int argc, _TCHAR* argv[])
71 {
72     P(">> 声明对象,但不初始化时:");
73     A a;
74 
75     P(">> 声明对象同时用对象进行初始化时:");
76     A b = a;
77 
78     P(">> 先声明对象:");
79     A c;
80     P(">> 再对对象进行赋值时:");
81     c = a;
82     
83     P(">> 使用拷贝构造函数初始化时:");
84     A d(a);
85 
86     P(">> 在函数调用传入形式参数时:");
87     foo(a);
88 
89 
90     system("pause");
91     return 0;
92 }

输出:

>> 声明对象,但不初始化时:
调用构造函数
>> 声明对象同时用对象进行初始化时:
调用拷贝构造函数
>> 先声明对象:
调用构造函数
>> 再对对象进行赋值时:
调用赋值运算符
>> 使用拷贝构造函数初始化时:
调用拷贝构造函数
>> 在函数调用传入形式参数时:
调用拷贝构造函数
请按任意键继续. . .