【C++】类的默认成员函数——构造函数、析构函数、拷贝构造函数、赋值运算符重载

2023-11-09

一、前言

类的默认成员函数就是,如果我们不写,编译器就会自动生成的成员函数。

当然如果我们写了,就不会自动生成。

二、构造函数

1. 基本概念

构造函数是用于初始化对象的成员函数,在对象创建时会自动调用。

构造函数的函数名和类名相同,而且没有返回类型。
例子:

class Date
{
public:
	//这就是Date类的一个构造函数
	Date()
	{
		...
	}
	
private:
	...	
};

构造函数支持函数重载。
例子:

class Date
{
public:
	//全缺省的构造函数
	Date(int year = 1970, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//半缺省的构造函数
	Date(int year, int month = 12, int day = 31)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	...
	
private:
	int _year;
	int _month;
	int _day;
};

2. 初始化列表

初始化列表是构造函数的一部分,不管有没有显式写出,进入函数体前都会先经过初始化列表。

如果类中有自定义类型成员,对象创建时,初始化列表会自动调用该成员的构造函数。

例子:

class Date
{
public:
	//带初始化列表的构造函数
	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
		{}
	
private:
	int _year;
	int _month;
	int _day;
};

利用初始化列表,可以很好地对成员进行初始化。构造函数体内的准确来说是赋值操作,所以有些情况下必须使用初始化列表来初始化。

比如引用成员和 const 成员,因为它们创建时必须初始化,所以只能用初始化列表对其初始化。

对于自定义类型的成员,虽然初始化列表会自动调用它的构造函数,但是如果它的构造函数必须传参,就必须在初始化列表显式写出。所以自定义类型的成员,建议在初始化列表初始化。

3. 自动生成的构造函数

构造函数是类的默认成员函数,如果我们不写,就会自动生成。

自动生成的构造函数,不会处理内置类型的成员,只会帮自定义类型的成员调用它的构造函数。

考虑到我们创建对象时一般都有初始化内置类型成员的需求,因此建议尽量自己写构造函数。

三、析构函数

1. 基本概念

析构函数是用于清理资源的成员函数,在对象销毁时会自动调用。

析构函数的函数名:~ 类名
析构函数没有参数和返回类型。
例子:

class Date
{
public:
	//这就是Date类的析构函数
	~Date()
	{
		...
	}
	
private:
	...	
};

析构函数是不支持函数重载的,因此一个类中有且只有一个析构函数。

一般情况下,先构造的对象后析构,因为后构造的对象可能会依赖先构造的对象。

2. 自动生成的析构函数

析构函数是类的默认成员函数,如果我们不写,就会自动生成。

与构造函数类似,自动生成的析构函数也不会处理内置类型的成员,不过内置类型的成员也不用手动回收,系统会自动回收。

但是自动生成的析构函数会帮自定义类型的成员调用它的析构函数。类中如果有申请资源,一定要自己写析构函数手动回收资源,否则会内存泄漏。

四、拷贝构造函数

1. 基本概念

拷贝构造函数是类的默认成员函数,如果我们不写,就会自动生成。

拷贝构造是构造函数的重载。用已创建的对象来初始化新对象时,会自动调用新对象的拷贝构造函数。
当然,这两个对象得是相同类型才行。

拷贝构造只有一个参数(隐藏了一个指向新对象的 this),这个参数是已创建的对象的引用(传值传参会死递归,因为传值传参也是用已创建的实参来初始化新创建的形参,也要调用拷贝构造),建议用 const 修饰(否则不能用 const 对象来拷贝构造新对象,因为 const 对象只能 const 引用)。

例子:

class Date
{
public:
	//全缺省的构造函数
	Date(int year = 1970, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
	//这就是Date类的拷贝构造函数
	Date(const Date& d)
	{
		//_year 等同于 this->_year
		//因为这是在Date类里,所以能访问d的成员
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

Date d;//自动调用构造函数来初始化

Date d1(d);//这是拷贝构造
Date d2 = d;//这也是拷贝构造
//因为都是用已创建的d来初始化新对象

除了传值传参和上面的情况,传值返回也是拷贝构造。因为传值返回是先将返回对象拷贝到临时对象,再将临时对象返回的,临时对象就是用已创建的返回对象拷贝构造得到的。

2. 自动生成的拷贝构造函数

拷贝构造函数是类的默认成员函数,如果我们不写,就会自动生成。

自动生成的拷贝构造是浅拷贝,也就是按字节序拷贝数据(上面我们自己在 Date 类里写的就是浅拷贝)。

对于 Date 类这种类中没有申请资源的可以不写拷贝构造,用自动生成的就行。但是对于类中有申请资源的,一定要自己写深拷贝的拷贝构造,保证每个对象申请的是自己的资源。

五、赋值运算符重载

对于运算符重载不清楚的小伙伴,可以先看这篇文章:传送门

1. 基本概念

赋值运算符重载是类的默认成员函数,如果我们不写,就会自动生成。

赋值运算符重载就是把一个已创建的对象赋给另一个已创建的对象,也就是赋值操作。
例子:

class Date
{
public:
	Date& operator=(const Date& d)
	{
		//_year 等同于 this->_year
		_year = d._year;
		_month = d._month;
		_day = d._day;
		
		//赋值运算返回左操作数
		//出了函数对象还存在,可以引用返回提高效率
		return *this;
	}
	
private:
	int _year;
	int _month;
	int _day;
};

//d1、d2是两个已创建的对象
d1 = d2;//等同于 d1.operator=(d2)

这里区别于拷贝构造,拷贝构造是用已创建的对象来初始化新对象。

//d1、d2是两个已创建的对象

Date d3(d1);//拷贝构造
Date d4 = d2;//拷贝构造
d3 = d2;//赋值运算符重载
d4 = d1;//赋值运算符重载

2. 自动生成的赋值运算符重载

赋值运算符重载是类的默认成员函数,如果我们不写,就会自动生成。

自动生成的赋值运算符重载是浅拷贝,也就是按字节序拷贝数据(上面我们自己在 Date 类里写的就是浅拷贝)。

对于 Date 类这种类中没有申请资源的可以不写赋值运算符重载,用自动生成的就行。但是对于类中有申请资源的,一定要自己写深拷贝的赋值运算符重载,保证每个对象申请的是自己的资源。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】类的默认成员函数——构造函数、析构函数、拷贝构造函数、赋值运算符重载 的相关文章

随机推荐

  • ue5获取从http中get到的json信息的蓝图节点是什么?

    在 Unreal Engine 5 UE5 中 您可以使用 HTTP 请求 蓝图节点来发送 HTTP 请求 并使用 HTTP 响应 蓝图节点来获取 HTTP 响应 要获取从 HTTP 中 GET 到的 JSON 信息 您需要执行以下步骤 使
  • webpack之externals解析

    1 是什么 指定排除掉不想被webpack打包的模块 被排除掉的模块 是要在运行时依赖用户环境去获取的 所以 用户的环境必须有被排除掉的包 2 既然模块不被打包 那么项目中的引入语句如何处理呢 webpack会根据你对模块的配置 将引入语句
  • CentOS7(Linux)详细安装教程(图文详解)

    一 软件准备 本文CentOS7安装在VMware Workstation虚拟机软件 故安装前请自行安装该软件 VMware Workstation官网链接 VMware Workstation官网地址 CentOS7下载地址 centos
  • 技术运营的工作是什么?

    什么是技术运营 技术运营到底是干什么的 本问作者艺璇分享了她的工作心得 关于作者 我于15年本科毕业加入阿里 4年前端开发 4年技术运营 目前主要工作方向是技术发展和技术影响力的打造 很开心受到邀请 来跟大家一起分享交流下 主要包含以下几部
  • 面试高频:为什么不用定时任务实现关闭订单?

    在电商 支付等领域 往往会有这样的场景 用户下单后放弃支付了 那这笔订单会在指定的时间段后进行关闭操作 细心的你一定发现了像某宝 某东都有这样的逻辑 而且时间很准确 误差在1s内 那他们是怎么实现的呢 一般的做法有如下几种 定时任务关闭订单
  • pytest当中conftest.py的使用

    目录 一 规则 1 conftest py文件是单独存放的一个单独夹具文件 名称不可修改 2 用处可以在不同的py文件当中使用同一个fixture函数 3 原则conftest py 要和运行的用例放在同一层级 例如testcase包下面
  • centos7服务器升级harbor-2.0.6至2.7.0

    centos7服务器升级harbor 2 0 6至2 7 0 1 升级harbor 2 0 6至2 4 0 使用指南 由于2 0 6版本不能直接升级到2 7 0版本 所以需要先过渡到2 4 0版本 原因是PG版本升级不兼容 2 0 6使用P
  • 如何利用TL431设计一个可调电压源

    TL431是一个三脚电压可控的稳压器件 常用的封装有TO 92 SOT 23 SOT 89 电路符号是这个 TL431常被用在参考电压 基准电压电路 用来替代稳压管 其中1脚是reference 2脚是Anode 3脚是Cathode TL
  • ARP(地址解析协议)

    ARP Address Resolution Protocol 地址解析协议 可以在以太网上 根据已知的IP地址查找主机的硬件地址 一 ARP的工作原理 我们以以太网的工作环境作为背景来探讨这一协议 串行链路由于是点到点链路 故而不需要AR
  • 微信网页开发分享

    首先提供一个微信官方地址点击打开链接 早期web项目中经常用到微信分享功能 现在整理一下 供记忆与分享 开发环境为JAVA H5 1 微信的开发环境不在多说 大概为 使用已备案的域名 设置 公众号设置 的三项域名 设置开发者密码 AppSe
  • Java直接杀死线程方法_如何杀死一个线程?

    1 简介 在这篇短文中 我们将讲述一下java中如果结束一个线程 事实上 这并没有想象中的那么简单 因为 Thread stop 方法已经被废弃啦 根据Oracle的解释 stop 方法可以导致被监视对象遭受破坏 2 使用一个Flag 我们
  • DWT数字水印算法(Python)

    DWT数字水印算法的基本原理 结合Arnold变换的基于DWT的数字水印的嵌入 充分利用了小波变换的特点 采用Haar小波 把原始图像及水印图像进行三级小波分解 然后在多分辨率分解后的频段嵌入水印信号 得到嵌入水印的图像 数字水印最重要的性
  • Keil5识别不到ST-Link的解决办法

    刚开始还以为是pack的问题 下载好多pack也没解决 后来发现其实是驱动的问题 从官网上下载驱动 之后进行基本的配置 如下所示 点击魔术棒标志 然后 然后 点击settings 点击add 添加自己的芯片类型 选择erase full c
  • 基于BERT模型实现文本分类任务(transformers+torch)

    BERT的原理分析可以看这 BERT Pre training of Deep Bidirectional Transformers for Language Understanding 论文笔记 代码实现主要用到huggingface的t
  • 如何保证MQ不丢失信息

    为了保证消息队列 MQ 不丢失信息 有以下几种方法可以考虑 增加冗余 通过将数据存储到多个不同的地方来防止数据丢失 使用持久化存储 通过将数据存储到磁盘上 而不是内存中 以确保数据不会丢失 引入数据备份 定期对数据进行备份 以防止意外数据丢
  • 二. go 常见控制结构实现原理之 select

    目录 一 基础问题 select 与channel select 与 channel 二 实现原理 1 select 底层结构 2 select选择case的执行逻辑 一 基础问题 select是Golang在语言层面提供的多路IO复用的机
  • Vue基础--组件的创建和使用

    一 组件化思想 一个页面中所有的处理概述逻辑全部放在一起 处理起来就会变得非常复杂 不利于后续的管理以及扩展 但是 我们将一个页面逻辑复杂的页面拆分成一个个小的功能块 每个功能块只完成属于自己这部分独立的功能 把大功能拆分成一个个小的功能
  • 51单片机0-9数字LED灯循环输出

    代码 include
  • 703n的OpenWrt配置一:安装和基本设置

    OpenWrt支持的路由可以从官网查到 顺藤摸瓜也可以找到固件的下载地址 如果知道路由器的cpu也可以从这里分类查找路由器型号 对于703n的ar71xx就是点我里面搜索703n找到的那几个文件 挑最小的固件下载 这样可以剩下更多空间安装其
  • 【C++】类的默认成员函数——构造函数、析构函数、拷贝构造函数、赋值运算符重载

    文章目录 一 前言 二 构造函数 1 基本概念 2 初始化列表 3 自动生成的构造函数 三 析构函数 1 基本概念 2 自动生成的析构函数 四 拷贝构造函数 1 基本概念 2 自动生成的拷贝构造函数 五 赋值运算符重载 1 基本概念 2 自