默认成员函数:析构、深浅拷贝

析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

特性

  1. 析构函数名时在类名前面加上字符~
CPP 复制代码
class Date
{
public:
	Date(int year, int month , int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	~Date()
	{
		......
	}
	
private:
		int _year = 0;
		int _month = 0;
		int _day = 0;
}
  1. 无参数无返回值类型,不带void

  2. 一个类只能由一个析构函数,如果未显式定义,系统会自动生成默认的析构函数。

  3. 析构函数不支持重载。

  4. 对象声明周期结束时,C++编译系统自动调用析构函数。

  5. 编译器生成的默认析构函数,对自定义类型成员调用它的析构函数。对内置类型不做处理。

  6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数。有资源申请时,一定要写,否则会造成资源泄露。

    对象的栈帧的开辟和销毁都是由编译器进行的。不需要析构

    动态开辟的空间资源才需要析构。

拷贝构造

拷贝构造函数:只有单个形参,该形参试对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

  • 浅拷贝:值拷贝
  • 深拷贝:深拷贝本质拷贝指向的资源,让两个被拷贝和拷贝者都有一样大的空间,一样大的值,但不是同一个空间。
  1. 拷贝构造函数是构造函数的一个重载形式

  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。

  3. 若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

  4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝,还需要自己显实现吗?如果像日期类这种类没有必要的,但是如果是别的需要开辟空间的呢?

    创建一个stack的对象s1,s1调用构造函数,申请了一个空间。s2使用s1拷贝构造,而Stack中没有显式定义的拷贝构造函数,此时编译器默认生成了一个拷贝构造函数,默认的拷贝构造函数是按照值拷贝的方式进行拷贝的,即将s1中的成员变量存储的值原封不动的赋值给了s2中的成员变量,拷贝结束之后,s2中的成员变量指向了和s1成员变量指向的同一片空间。

    当程序结束的时候,s2先销毁,s1后销毁,s2先调用析构函数对这片申请的空间进行了析构,然后s1销毁,此时s1并不知道这片内存空间已经销毁了,再次对这片空间进行了析构,此时就会崩溃。对一片内存空间进行了多次释放。

浅拷贝

  • 类中如果没有设计资源申请时,拷贝构造函数是否写都可以;
  • 一旦涉及到资源申请,则拷贝构造函数是一定要写的,否则就是浅拷贝。
  1. 拷贝构造的典型调用场景:
    • 使用已存在的对象创建对象
    • 函数参数类型未类类型对象
    • 函数返回值类型为类类型对象
  • 为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

  • 拷贝构造主要用于解决深拷贝的问题。

  • 深拷贝本质拷贝指向的资源,让两个被拷贝和拷贝者都有一样大的空间,一样大的值,但不是同一个空间。

深拷贝

CPP 复制代码
//Stack st2(st1);
Stack(const Stack& st)
{
	_a = (int*)malloc(sizeof(int) * st._capacity);
	if(_a == nullptr)
	{
		perror("malloc fail");
		exit(-1);
	}
	memcpy(_a,st._a,sizeof(int)*st._top);
	_top = st._top;
	_capacity = st._capacity;
}
  • 两个已经存在的对象拷贝,赋值拷贝
  • 一个已经存在的对象拷贝初始化另一个要创建的对象,就是拷贝构造
CPP 复制代码
A aa1(1);

A aa2(aa1);    //拷贝构造
A aa3 = aa1;   //拷贝构造

aa2 = aa3;    //赋值拷贝
相关推荐
dr李四维2 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
cherub.3 分钟前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++
暮色_年华17 分钟前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++
重生之我是数学王子26 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
我们的五年1 小时前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
做人不要太理性1 小时前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.1 小时前
2、桥接模式
c++·桥接模式
chnming19871 小时前
STL关联式容器之map
开发语言·c++
程序伍六七2 小时前
day16
开发语言·c++
小陈phd2 小时前
Vscode LinuxC++环境配置
linux·c++·vscode