C++ 中类的拷贝、赋值、销毁的实例详解
本篇文章我们一共讲解一下几个知识点:
类的拷贝构造函数。
类的拷贝赋值运算符。
类的析构。
好了one by one
如果我们没有定义类的拷贝构造函数的话,那么编译器会为我们合成默认拷贝构造函数----合成拷贝构造函数。
和成拷贝构造函数的操作是将其参数的各个成员拷贝到正在创建的对象中去,每个成员的类型决定了他是如何被拷贝的:对类类型的成员,会使用其拷贝构造函数,内置类型的成员则是直接拷贝,虽然我们不能直接拷贝一个数组,但是合成拷贝构造函数会逐个的拷贝一个数组类型的成员。
下面我们用代码演示一下合成拷贝构造函数的功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <iostream>
using namespace std;
/*
代码模仿合成拷贝构造函数的功能
*/
class Sales_data
{
public :
Sales_data();
//我们只是为了读者更好的理解还原了一下合成拷贝构造函数所实现的功能,实际上我们是看不见的
Sales_data( const Sales_data& s);
~Sales_data();
private :
string bookNo;
int units_sold = 0;
double revenue = 0.0;
};
Sales_data::Sales_data()
{
}
Sales_data::Sales_data( const Sales_data& s) :
bookNo(s.bookNo), units_sold(s.units_sold), revenue(s.revenue){
}
Sales_data::~Sales_data()
{
}
|
好了,我们定义拷贝构造函数也是如此定义的,我解释一下为什么参数表里面是一个静态的引用:
1)我们不想改变该引用的值,只是用来进行拷贝。
2)我们必须声明为引用,如果写成类的话,则又会调用该类的拷贝构造函数,在那个拷贝构造函数中又会调用拷贝构造函数,这样陷入死循环。
我们在来学习一下拷贝赋值运算符:
和拷贝构造函数一样,如果我们不定义拷贝赋值运算符的话,编译器将会为我们合成一个,我们下面用代码来模仿一下吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#include <iostream>
using namespace std;
/*
代码模仿拷贝赋值运算符
*/
class Sales_data
{
public :
Sales_data();
//拷贝赋值运算符的默认合成
Sales_data& operator = ( const Sales_data & s);
~Sales_data();
private :
string bookNo;
int units_sold = 0;
double revenue = 0.0;
};
Sales_data::Sales_data()
{
}
Sales_data& Sales_data::operator = ( const Sales_data & s) { //为什么我们的返回值一定是引用类型呢?这是因为我们可以进行链式编程而做的:s1 = s2 =s3;
bookNo = s.bookNo;
units_sold = s.units_sold;
revenue = s.revenue;
return * this ;
}
Sales_data::~Sales_data()
{
}
|
好了,我们定义拷贝赋值运算符也是如此,我们就不一一赘述了。
我来在来谈一谈;类的构造函数初始化和类的析构函数销毁过程的一些细节性问题。
1比如我们定义了一个构造函数,实际上在参数化赋值列表处及大括号之前,才是我们真正进行初始化的地方,在大括号之中做的操作只是进行了拷贝赋值操作。
这一点我们要清楚的认识到,要不然在对const对象进行初始化是就有问题了,因为const对象只能初始化。
2比如我们定义了一个析构函数,注意了,我们在() {之间的部分才是做了真正的类成员变量的析构操作,{}里面使我们进行的自定义操作,不一定是什么析构,应为析构基本已经完成了。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
原文链接:http://blog.csdn.net/c1523456/article/details/76531432