C\C++_构造函数和析构函数

2023-11-07

1. 系统提供构造函数规则

  1. 系统默认会提供默认无参构造函数、拷贝构造(浅拷贝)和析构函数
  2. 如果用户定义拷贝构造函数,c++不会再提供任何默认构造函数
  3. 如果用户定义了普通有参构造函数(非拷贝),C++不在提供默认无参构造,但是会提供默认拷贝构造(浅拷贝)

1.1 代码示例

	Person()	//< 默认构造,自定义后,则编译器不再提供默认构造函数
	{
		std::cout << "enter into default constructor\n";
		this->m_nAge = 0;
	}

	Person(const Person&per)	//< 拷贝构造函数,自定义后,编译器则不再提供
	{
		std::cout << "enter into copy constructor\n";
		this->m_nAge = per.m_nAge;
	}

	~Person()
	{
		std::cout << "enter into destructor\n";
	}

private:
	int m_nAge;
};

2. 默认构造函数

  1. 定义时的歧义:
class Person
{
public:
	Person()	//< 默认构造,自定义后,则系统不再提供默认构造函数
	{
		this->m_nAge = 0;
	}

	Person(int nAge = 10)		//< 带默认参数会和默认构造产生歧义
	{
		this->m_nAge = nAge;
	}

private:
	int m_nAge;
};

int main()
{
	Person p;	//< 报错:使用哪个默认构造,会有歧义
	
	return 0;
}

3. 拷贝构造函数

3.1 深拷贝和浅拷贝

  • 如果类成员变量中存在指向堆空间的数据,那浅拷贝会导致重复释放内存的异常(解决上述问题就需要深拷贝)

3.2 调用拷贝构造的时机

	Person()	//< 默认构造,自定义后,则编译器不再提供默认构造函数
	{
		std::cout << "enter into default constructor\n";
		this->m_nAge = 0;
	}

	Person(const Person&per)	//< 拷贝构造函数,自定义后,编译器则不再提供
	{
		std::cout << "enter into copy constructor\n";
		this->m_nAge = per.m_nAge;
	}

	~Person()
	{
		std::cout << "enter into destructor\n";
	}

private:
	int m_nAge;
};

void CallPer(Person per)
{
	std::cout << "enter into CallPer function\n";
}

Person ReturnPer(Person &per)
{
	return per;
}

int main()
{
	//! 1.用对象来初始化新建对象,会调用拷贝构造函数
	//Person p1;
	//Person p2 = p1;

	//! 2.对象以值传递的方式传给函数参数,会调用拷贝构造函数
	//Person p3;
	//CallPer(p3);	//< 函数参数会有1个临时变量来接受传递的对象 Person per = p3,则再次调用拷贝构造

	//! 3.函数以值传递的方式返回对象
	Person p4,p5;
	p5 = ReturnPer(p4);	//< 返回p4的引用per,用p5 = per 会调用拷贝构造函数

	return 0;
}

4. 带参构造函数

4.1 带单个参数


//! explicit关键字:适用于单参的构造函数,只能显示的调用构造函数,不能隐式的调用
class Person
{
public:
	Person()			
	{
		this->m_nAge = 0;
	}

	Person(int nAge)	//< 带单个参数的有参构造,不加关键字explicit,则容易发生隐士转换;如果加了explicit关键字,隐士转换会报错
	{
		this->m_nAge = nAge;
	}

private:
	int m_nAge;
};

int main()
{
	Person p = 10;	//< 隐士转换:将int类型转换成Person类型;等同于Person p = Person(10);Person(10)即隐式的调用了有参构造Person(int nAge)

	return 0;
}

5. 不使用拷贝构造和拷贝赋值运算符

5.1 方法一

将他们都声明为私有,不需要实现

缺点:万一有成员函数或者friend函数不小心调用它们,报错会推迟到链接的时候才会报错。通常报错越早越好

class CPerson
{
public:
	CPerson(){}
	~CPerson(){}
	void Display(const CPerson& p)
	{
		*this = p;	//<	成员函数调用拷贝赋值运算符(链接的时候才报错)
	}

private:
	CPerson(const CPerson&);
	CPerson& operator=(const CPerson&);
};

void Test01()
{
	CPerson p1;
	CPerson p2;
	//p1.Display(p2); 
}

5.2 方法二

为当前类设置一个专门为了阻止拷贝动作而设计的基类

注:当有成员函数或friend函数尝试拷贝当前类对象,编译器会试着生成一个copy构造函数和一个copy assignment操作符,这些函数的“编译器生成版”会尝试调用其基类的对应星弟,那些调动会被编译器拒绝,因为其基类的拷贝函数是private

class CUncopyable
{
protected:				//<	允许derived对象构造和析构
	CUncopyable(){}
	~CUncopyable(){}
private:
	CUncopyable(const CUncopyable&);			//< 组织copying
	CUncopyable& operator=(const CUncopyable&);
};

class CAnimal: private CUncopyable
{
public:
	CAnimal()
		:m_a(0)
	{

	}
	void Display(const CAnimal& p)
	{
		//*this = p;	//<	成员函数调用拷贝赋值运算符(编译的时候就报错)
		cout << m_a << endl;
	}

private:
	int m_a;
};

参考effective c++ 第三版 条款06 若不想使用编译器自动生成的函数,就该明确拒绝

6. 析构

6.1 别让异常逃离析构

  • 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序(std::abort())。
  • 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。

参考:effective c++ 第三版 条款08:别让异常逃离析构函数

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

C\C++_构造函数和析构函数 的相关文章

  • 双缓冲列表框

    我有一个 CheckedListBox WinForms 控件 它继承自 ListBox 谷歌搜索显示问题出在 ListBox 该控件锚定到其窗体的所有四个边 当调整表单大小时 列表框会出现难看的闪烁 我尝试继承 CheckedListBo
  • 类变量在其定义范围内?

    这可能是一个愚蠢的问题 我正在尝试制作文本泥 我需要每个 Room 类包含其他 Room 类 以便在尝试移动到它们或从它们获取信息时可以引用 但是 我不能这样做 因为我显然无法在其定义中声明一个类 那么 我该怎么做呢 当我说我做不到时 我的
  • 递归显式模板实例化以导出库的符号

    在我之前的问题中我问过递归显式模板实例化是否可能 https stackoverflow com questions 7395113 is recursive explicit template instantiation possible
  • 递归显式模板实例化可能吗?

    给定一个类似的模板 template
  • Web API 复杂参数属性均为 null

    我有一个 Web API 服务调用可以更新用户的首选项 不幸的是 当我从 jQuery ajax 调用中调用此 POST 方法时 请求参数对象的属性始终为 null 或默认值 而不是传入的值 如果我使用 REST 客户端调用相同的方法 我使
  • 在 std::forward 中它如何接受右值?

    看看斯科特 迈耶的有效的现代 C 第200 201页 建议的简化实施std forward可能是 在其他地方看到了正确的实现 template
  • iPhone 编程游戏

    使用 Objective C 还是 C 为 iPhone 编写游戏最好 像 Flight Control 这样的游戏会用什么语言编写 图形应采用什么格式才能在 iPhone 上正确显示并快速加载 像 Flight Control 这样的游戏
  • 如何使用 Regsvr32 注册 .NET COM DLL?

    我有一个使用 COM DLL 的 VB6 应用程序 该DLL是用C 编写的 在 C 项目属性中 我检查了 Register for COM interop 选项 VB6 应用程序在我的开发机器上运行良好 C 代码完全遵循以下格式 CodeP
  • 类型定义存在于两个库中

    我正在使用 NET 4 5 构建 ASP NET Web 窗体网站 错误 The type System ComponentModel DataAnnotations Schema ForeignKeyAttribute exists in
  • C# - 如何从 Steam 交易 API 获取图标的 URL(编码)

    以下是 API 为每个项目返回的 XML 部分
  • 在 .NET Core 上通过 MEF 将参数传递给插件构造函数?

    我花了几个小时试图弄清楚如何通过 MEF System Composition 将参数传递给插件构造函数 但一切都无济于事 不用说 相关文档很少 查看源代码也没有帮助 这曾经非常容易做到 使用 CompositionHost Compose
  • 从动态服务器中抓取 html 列表数据

    哈喽大家好 抱歉提出转储问题 这是我最后的手段 我发誓我尝试了无数其他 Stackoverflow 问题 不同的框架等 但这些似乎没有帮助 我有以下问题 一个网站显示一个数据列表 前面有大量的 div li span 等标签 它是一个很大的
  • 将控制台输入和输出重定向到文本框

    您好 提前致谢 我正在尝试 非常努力 将控制台输入和输出重定向到文本框 到目前为止 输出工作正常 但问题在于输入 例如 我无法执行一个简单的程序来执行以下操作 Console WriteLine 请输入您的姓名 字符串名称 Console
  • 给出对象的指针作为参数

    假设我有 void func foo obj 我有 foo object 我该如何制作object进入争论func 只需取消引用它即可 func object
  • 在浏览器中测试wcf服务

    我无法在浏览器中调用基本的 wcf web 方法 即使使用
  • 向量和常量

    考虑一下这个 void f vector
  • ASP.NET Core中间件如何进行DI?

    我正在尝试将依赖项注入到我的中间件构造函数中 如下所示 public class CreateCompanyMiddleware private readonly RequestDelegate next private readonly
  • 对嵌套属性使用 XmlAttributeOverrides

    我试图使用 XmlAttributeOverrides 来控制类序列化后哪些类属性出现在 xml 中 它适用于 根 类上的属性 但不适用于嵌套属性 这是一个简单的例子来说明我想要完成的任务 我的类层次结构如下 public class Ma
  • 如何在 OpenCV 中删除 mouseCallback

    在使用 C 的 OpenCV 中 有没有办法删除 mouseHandler int event int x int y int flags void param 通过函数添加到窗口 image window cv setMouseCallb
  • 将 Web 场迁移到 ASP.NET 运行时版本 4,同时保持会话

    我们已将 Web 应用程序从 net 运行时 2 v 3 5 迁移到 net 运行时 4 v 4 5 我有一个部署问题 我们的 sessionstate 服务器是一个 stateserver 并在单独的服务器上运行框架 2 中的 aspne

随机推荐

  • Flutter插件开发-(进阶篇)

    一 概述 Flutter也有自己的Dart Packages仓库 插件的开发和复用能够提高开发效率 降低工程的耦合度 像网络请求 http 用户授权 permission handler 等客户端开发常用的功能模块 我们只需要引入对应插件就
  • ell服务器专用pe系统,GitHub - elltor/smpe-admin: 后端通用开发框架

    SMPE ADMIN后台管理系统 项目简介 一个基于EL ADMIN Spring Boot 2 1 0 Mybatis Plus JWT Spring Security Redis Vue的前后端分离的后台管理系统 开发文档 待完善 默认
  • 集群架构总结(Kafka、redis,zk,es)

    ZK集群 1 zk集群节点可见 通过配置文件达到节点间相互可见 2 为什么集群设置奇数个节点 1 奇数节省资源 zk容错 zk节点剩下的个数必须要大于挂掉的节点 大于n 2 整个集群才可用 5节点容错2个 6节点容错2个 2 奇数节点集群可
  • CPPUTest 单元测试框架(针对 C 单元测试的使用说明)

    CPPUTest 虽然名称上看起来是 C 的单元测试框架 其实它也是支持测试 C 代码的 本文主要介绍用CPPUTest来测试 C 代码 C 没用过 平时主要用的是C C 相关的内容都省略了 本文基于 debian v7 6 x86 64
  • 2023零基础 Python 学习路线图,转行学Python让你少走弯路~

    这是我刚开始学习python时的一套学习路线 从入门到上手 不敢说精通 哈哈 希望对大家有帮助哈 大家需要高清得python学习路线可以私信我 学习 即可获取 一 Python入门 环境搭建 变量 数据类型 二 Python运算符 条件结构
  • 小程序常见的面试题

    小程序常见的面试题 1 简单描述下微信 程序的相关 件类型 答 微信 程序项 结构主要有四个 件类型 如下 WXML 是框架设计的 套标签语 结合基础组件 事件系统 可以构建出 的结构 内部主要是微信 定义的 套组件 WXSS WeiXin
  • Linux操作系统之进程间通讯—共享内存与消息队列

    文章目录 一 共享内存 1 共享内存的原理 2 共享内存的实现 三 消息队列 1 消息队列原理 2 消息队列实现 一 共享内存 1 共享内存的原理 共享内存为多个进程之间共享和传递数据提供了一种有效的方式 共享内存是先在物理内存上申请一块空
  • 2.linux git显示分支名

    linux git显示分支名 linux git显示分支名 解决linux里面git不会显示分支名 1 在 bash profile 里面添加 display the git branch name function git branch
  • 视觉SLAM理论与实践第四节课习题

    4 矩阵微分 2 分 约 1 5 小时 在优化中经常会遇到矩阵微分的问题 例如 当 变量为向量 x 求标量函数 u x 对 x 的导数时 即 为矩阵微分 通常线性代数教材不会深 探讨此事 这往往是矩阵论的内容 我在 ppt 录下为你准备了
  • ubuntu18一直紫屏,无法进入图形界面

    ubuntu18一直紫屏 无法进入图形界面 一直紫屏的原因 解决方法 首先进入想办法进入桌面环境 第一种方法 第二种方法 然后修改一些配置文件 一直紫屏的原因 使用apt upgrade更新系统后 出现桌面卡死 很是纳闷 也重装了两次系统
  • ChatGPT研究分享:机器第一次开始理解人类世界

    0 为什么会对ChatGPT感兴趣 一开始 我对ChatGPT是没什么关注的 无非就是有更大的数据集 完成了更大规模的计算 所以能够回答更多的问题 但后来了解到几个案例 开始觉得这个事情并不简单 我先分别列举出来 具体解读在文末说明 1 C
  • ChatGPT简单介绍

    div class markdown views div
  • Git Extensions的安装与使用

    一 介绍 Git Extensions是一个工具包 旨在使Windows下的Git更直观 功能 Git的Windows资源管理器集成 功能丰富的Git用户界面 32位和64位支持 二 安装 csdn下载地址 GitExtensionhttp
  • 新唐NUC980使用记录:访问以太网(LAN8720A) & 启用SSH

    文章目录 目的 修改内核以访问以太网 制作根文件系统并启用SSH 总结 目的 这篇文章主要测试访问以太网 PHY为LAN8720A 以及启用SSH 这篇文章中内容均在下面的开发板上进行测试 新唐NUC980使用记录 自制开发板 基于NUC9
  • 为什么一定要使用二级指针,而一级为什么就不行呢??

    为什么一定要使用二级指针 而一级为什么就不行呢 不是说函数中传递指针 在函数中改变指针的值 就是在改变 实参中的数据信息嘛 额 其实吧 上边说的也对 可问题就在这块了 问题是 在建立二叉树的过程中 不是改变了形参的值 而是 改变了形参的指向
  • Docker: network nat is ambigous

    初次使用docker投入开发使用 感觉不要太爽 强烈推荐入坑docker 但docker国内相关资料偏少 无论是学习或是排查问题 都不是很方便 入门学习推荐微信公众号magiccodes的 Docker最全教程 系列文章 有兴趣可自行查找
  • Kubernetes部署redis主从集群

    目标 部署Redis leader节点 部署两个follower节点 一 部署 leader节点 redis leader yaml apiVersion v1 kind Service metadata name redis leader
  • IDEA创建Web Project图解

    截图方式全程演示如何使用IntelliJ IDEA创建一个Web Project 以及如何部署到Tomcat 如何打成war包 详细请看截图 虽然没多少文字全是截图 但该有的文字说明截图上也有 如果还有什么疑问 请加裙交流
  • bfs 解决最短路问题

    前提 边权都一样时 才能用bfs求最短路 问题 给定一个 n mn m 的二维整数数组 用来表示一个迷宫 数组中只包含 00 或 11 其中 00 表示可以走的路 11 表示不可通过的墙壁 最初 有一个人位于左上角 1 1 1 1 处 已知
  • C\C++_构造函数和析构函数

    文章目录 1 系统提供构造函数规则 1 1 代码示例 2 默认构造函数 3 拷贝构造函数 3 1 深拷贝和浅拷贝 3 2 调用拷贝构造的时机 4 带参构造函数 4 1 带单个参数 5 不使用拷贝构造和拷贝赋值运算符 5 1 方法一 5 2