C++拷贝构造函数

2023-11-02

目录

前言

一、拷贝构造函数

1. 概念

         2. 笔试题-拷贝构造的次数

3. 特征

         1). 拷贝构造函数是构造函数的一个重载形式。

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

那怎么理解无穷递归了?

那为什么最好要用const修饰了?

3).  若未显式定义,编译器会生成默认的拷贝构造函数。

        3.1调试过程了解一下:

        3.2如果没使用默认的拷贝构造,调试过程:

什么时候需要深拷贝?

总结


前言

C++类与对象(二)(中)拷贝构造函数

一、拷贝构造函数

1. 概念

        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?可以,拷贝构造函数就能满足你的要求。
        拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

2. 笔试题-拷贝构造的次数

以下代码共调用多少次拷贝构造函数: ( )

Widget f(Widget u)

{  

  Widget v(u);

  Widget w=v;

  return w;

}

main(){

  Widget x;

  Widget y=f(f(x));

}


A.9
B.3
C.5
D.7

         1).f(x);//传值传参,用x去初始化u(void f(Weight u))//自定义变量传值传参就会调用拷贝构造函数,调用后在再进入void f(Weight u)

#include<iostream>
using namespace std;
class Weight
{
public:
	Weight()
	{
		cout << "Weight" << endl;
	}
	Weight(const Weight& w)
	{
		cout << "Weight(consy Weight& w)" << endl;
	}
};

void f(Weight u)
{
}
int main()
{
	Weight x;
	f(x);//传值传参,用x去初始化u(void f(Weight u))
	//自定义变量传值传参就会调用拷贝构造函数
	//调用后在再进入void f(Weight u)
	return 0;
}

         2). Weight w = v也调用拷贝构造

         3)注意:一个表达式中,连续步骤的构造+拷贝构造,或者拷贝构造+拷贝构造,胆大的编译器可能就会进行优化合二为一,所以这里只输出了4次Weight(const Weight& w)        

#include<iostream>
using namespace std;
class Weight
{
public:
	Weight()
	{
		cout << "Weight" << endl;
	}
	Weight(const Weight& w)
	{
		cout << "Weight(consy Weight& w)" << endl;
	}

	~Weight()
	{
		cout << "~Weight()" << endl;
	}
};

Weight f(Weight u)
{
	Weight v(u);
	Weight w = v;
	return w;
}
int main()
{
	Weight x;
	//Weight();//匿名对象的生命周期只在这一行
	Weight ret = f(x);
	//注意:一个表达式中,连续步骤的构造+拷贝构造,或者拷贝构造+拷贝构造,胆大的编译器可能就会进行优化
	//合二为一,所以这里只输出了4次Weight(const Weight& w)


	return 0;
}

3. 特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

class Data
{
public:
	Data(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Data(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data d1(2022,10,7);
	Data d2(d1);
	d2.Print();
	d1.Print();
	return 0;
}

对于以上代码:

Data d2(d1);
拷贝构造函数简单理解就是把d1给d2
注意拷贝函数的参数只有一个且必须是类类型对象的引用,且一般会要求加上const,以保证d1不可修改
回顾一下引用的概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,
编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
注意:不会额外开辟空间,内存空间是共用的。
通过d2.Print();d1.Print();可以发现输出结果是一样的,进行了拷贝

 看下图,提示非法的复制构造函数:即使用传值方式编译器直接报错,会引发无穷递归调用。

那怎么理解无穷递归了?

        因为自定义类型变量d1的临时拷贝或者说是对于自定义类型变量,当同类型的参数(同类型的对象)进行传参时,需要先调用拷贝构造函数。
下面将用vs2019进行调试,显示一下调用拷贝构造函数过程;

1).设置断点,F10进入调试,F5进入断点,显示如下:

 2)F11下一步,发现调用拷贝构造函数

 3)d1给d2完成,见右边调试结果

 因为C++对于自定义类型变量,进行传参时会调用拷贝构造函数,那么就会出现套娃现象:

        我Data(Data d)这样写拷贝构造函数的时候,对于Data d2(d1),对于自定义变量的传参,就调用一下拷贝构造函数,而调用拷贝构造函数,又会进行传值传参,此时又要调用拷贝构造函数,依此循环......,而Data(const Data& d)这样就不会出现这个问题。

        如果拷贝构造函数的参数不是当前类的引用,而是当前类的对象,那么在调用拷贝构造函数时,会将另外一个对象直接传递给形参,这本身就是一次拷贝,会再次调用拷贝构造函数,然后又将一个对象直接传递给了形参,将继续调用拷贝构造函数……这个过程会一直持续下去,没有尽头,陷入死循环。

        或者这样理解,我将d1传过去变成Data(d1),又是拷贝构造,之后又是Data(Data d1)又是拷贝构造,一直拷贝构造。。。。。

那为什么最好要用const修饰了?

首先先简单回顾一下const

对于const
const放*右边,表示指针变量本身不能被修改
const放在*左边表示指针所指向内容,不能通过指针改变(这里的左边可以int之前,也可以是int之后*之前,总之只要是*左边即可)
对于构造函数,存在写反的问题,如下:

    对于两种情况

 如果是02的时候:输出随机值。

在Data(Data& d)-02下,写反后,对于Data d2(d1); d是d1的别名,this是d2, 我们要拷贝出d2, 就是要把d1给d2,但是d._year = _year; 对于这句话,是将this给了d1(注意隐含的this指针是这样,this->_year),相当于变成了d2给了d1, 而d2是随机值,所以print都是随机值。

3). 若未显式定义,编译器会生成默认的拷贝构造函数。

class Data
{
public:
	Data(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//使用默认的拷贝构造函数
	// 1.若未显式定义,编译器会生成默认的拷贝构造函数。
	// 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
	//Data(const Data& d)
	//{
	//	_year = d._year;
	//	_month = d._month;
	//	_day = d._day;
	//}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void Func(Data d)
{
	d.Print();
}
int main()
{
	Data d1(2022,10,13);
	Data d2(d1);
	Func(d1);//传参就会先调用拷贝构造函数
	d2.Print();
	return 0;
}
拷贝构造函数的特点是( )
A.该函数名同类名,也是一种构造函数,该函数返回自身引用
B.该函数只有一个参数,是对某个对象的引用
C.每个类都必须有一个拷贝初始化构造函数,如果类中没有说明拷贝构造函数,则编译器系统会自动生成一个缺省拷贝构造函数,作为该类的保护成员
D.拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象

A.拷贝构造函数也是一构造函数,因此不能有返回值

B.该函数参数是自身类型的对象的引用

C.自动生成的缺省拷贝构造函数,作为该类的公有成员,否则无法进行默认的拷贝构造

D.用对象初始化对象这是拷贝构造函数的使命,故正确

 3.1调试过程了解一下:

1)Data d1(2022,10,13);f11跳到自己写的全缺省的Data构造函数,可以看到d1初始化成功。

 2)若使用默认的由编译器生成的拷贝构造函数,f11会直接到Func(d1),发现d2变成和d1一样,即进行了按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

注意区分:默认生成构造函数对于内置类型成员变量不做处理,对于自定义类型成员变量才会处理,其中c++把变量分成两种,内置类型/基本类型:int/char/double/指针 ,自定义类型:class/struct去定义类型对象。

3)调用Print 

 

3.2如果没使用默认的拷贝构造,调试过程:

 1)当我运行到Data d2(d1)的时候就会调用自己所写的构造函数

 2)拷贝成功后

 3)当到了Func(d1)后继续按F11,发现又去调用了拷贝构造函数,再f11进入的func函数本体,是因为对于自定义类型变量,当同类型的参数(同类型的对象)进行传参时,需要先调用拷贝构造函数。

 

 4)最后就是调用print的过程

 注意:但这并不能说明我们就可以肆无忌惮的使用默认生成的拷贝构造函数,看如下代码:

        因为:默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝

#include<iostream>
using namespace std;
class Stack
{
public:
	Stack(int capacity = 10)//构造函数,函数名为类名Stack,无返回值
	{
		_a = (int*)malloc(sizeof(int*) * capacity);
		if (_a == nullptr)
		{
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;//可写可不写
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
class MyQueue
{
public:
	void push(int x)
	{

	}
	int pop()
	{

	}//注意:函数都在公共区
private:
	Stack _st1;
	Stack _st2;
};
int main()
{
	Stack st1(10);
	Stack st2(st1);
	return 0;
}

 调试:调用了两次析构函数,是因为默认的拷贝构造函数对象按内存存储按字节序完成拷贝,那么_a指向的是同一块空间。

 思考一个问题:那如果不是动态开辟的这种类型,是数组可以吗?

_a是指针的时候,拷贝的是指针,但是数组是可以的,且它们所在的内存区域也不一样。

那什么是深拷贝,什么是浅拷贝了?

        对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。但是当类持有其它资源时,例如动态分配的内存、指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据。 

        比如之前缩写的stack类,显式地定义了拷贝构造函数,它除了会将原有对象的所有成员变量拷贝给新对象,还会为新对象再分配一块内存,并将原有对象所持有的内存也拷贝过来。这样做的结果是,原有对象和新对象所持有的动态内存是相互独立的,更改一个对象的数据不会影响另外一个对象。 这种将对象所持有的其它资源一并拷贝的行为叫做深拷贝,我们必须显式地定义拷贝构造函数才能达到深拷贝的目的。  

        而默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。这种拷贝不会开辟一块新的空间,即把d1对象全拷给d2。

什么时候需要深拷贝?

         如果一个类拥有指针类型的成员变量,那么绝大部分情况下就需要深拷贝,因为只有这样,才能将指针指向的内容再复制出一份来,让原有对象和新生对象相互独立,彼此之间不受影响。如果类的成员变量没有指针,一般浅拷贝足以。     

那我们再看一段代码:

#include<iostream>
using namespace std;
class Stack
{
public:
	Stack(int capacity = 10)//构造函数,函数名为类名Stack,无返回值
	{
		_a = (int*)malloc(sizeof(int*)*capacity);
		if (_a == nullptr)
		{
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	Stack(const Stack& st)
	{
		_a = st._a;
		_top = st._top;
		_capacity = st._capacity;
	}
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;//可写可不写
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
class MyQueue
{
public:
	void push(int x)
	{

	}
	int pop()
	{

	}//注意:函数都在公共区
private:
	Stack _st1;
	Stack _st2;
};
int main()
{
	Stack st1(10);
	Stack st2(st1);
	return 0;
}

为什么运行崩溃了?经过调试发现了一个这样的错误,为什么?

 经过调试发现,这里就不粘贴图片了,调试方法同上即可,该代码调用了两次~stack,析构函数调用了两次,即进行了两次释放,但是他之前已经进行了拷贝,即已经将st1给了st2,那么会进行两次释放,多次释放导致运行崩溃,但是编译会通过,因为代码的语法没有问题。

总结

        拷贝构造函数,一般的类,自己生成拷贝构造函数就够用了,只有STACK类。自己直接管理资源的,需要子实现深拷贝。

      内置类型的值拷贝,浅拷贝;自定义类型的成员,去调用这个成员的拷贝构造函数。                

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

C++拷贝构造函数 的相关文章

  • 具有子列表属性映射问题的自动映射器

    我有以下型号 Models public class Dish Required public Int64 ID get set Required public string Name get set Required public str
  • ASP.NET MVC 中的经典 ASP (C#)

    我有一个应用程序想要 最终 转换为 ASP NET MVC 我想要进行全面的服务升级 到 ASP NET 但想要使用当前的 ASP 内容来运行当前的功能 这样我就可以在对新框架进行增量升级的同时升级小部分 该站点严重依赖于不太成熟的 VB6
  • OpenCv读/写视频色差

    我试图简单地使用 openCV 打开视频 处理帧并将处理后的帧写入新的视频文件 我的问题是 即使我根本不处理帧 只是打开视频 使用 VideoCapture 读取帧并使用 VideoWriter 将它们写入新文件 输出文件看起来比输入更 绿
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • 如何识别 WPF 文本框中的 ValidationError 工具提示位置

    我添加了一个箭头来指示工具提示中的文本框 当文本框远离屏幕边缘时 这非常有效 但是当它靠近屏幕边缘时 工具提示位置发生变化 箭头显示在左侧 Here is the Image Correct as expected since TextBo
  • 如何将“外部模板”与由同一类中的模板化成员使用的嵌套类一起使用?

    首先 一些背景信息 我尝试以 Herb Sutter 在他的解决方案中介绍的方式使用 Pimpl 习语 得到了 101 http herbsutter com gotw 101 这在头文件中看起来像这样 include pimpl h h
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • 通过 NHibernate 进行查询,无需 N+1 - 包含示例

    我有一个 N 1 问题 我不知道如何解决它 可以在这个问题的底部找到完全可重复的样本 因此 如果您愿意 请创建数据库 设置 NUnit 测试和所有附带的类 并尝试在本地消除 N 1 这是我遇到的真实问题的匿名版本 众所周知 这段代码对于帮助
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 将代码拆分为标头/源文件

    我从 Asio 的示例页面中获取了以下代码 class tcp connection public boost enable shared from this
  • 是否可以有一个 out ParameterExpression?

    我想定义一个 Lambda 表达式out范围 有可能做到吗 下面是我尝试过的 C Net 4 0 控制台应用程序的代码片段 正如您在 procedure25 中看到的 我可以使用 lambda 表达式来定义具有输出参数的委托 但是 当我想使
  • 耐用功能是否适合大量活动?

    我有一个场景 需要计算 500k 活动 都是小算盘 由于限制 我只能同时计算 30 个 想象一下下面的简单示例 FunctionName Crawl public static async Task
  • 为什么拆箱枚举会产生奇怪的结果?

    考虑以下 Object box 5 int int int box int 5 int nullableInt box as int nullableInt 5 StringComparison enum StringComparison
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • 蓝桥BASIC-18 矩形面积交 思路分析

    问题描述 平面上有两个矩形 它们的边平行于直角坐标系的X轴或Y轴 对于每个矩形 我们给出它的一对相对顶点的坐标 请你编程算出两个矩形的交的面积 输入格式 输入仅包含两行 每行描述一个矩形 在每行中 给出矩形的一对相对顶点的坐标 每个点的坐标
  • Qt开发上位机软件建立经典蓝牙通讯

    Qt开发上位机软件建立经典蓝牙通讯 之前做了一个具有经典蓝牙通讯功能的Windows上位机软件 在网上学习了相关博客以及参考了官方经典蓝牙例程之后 总结出了使用Qt建立经典蓝牙通讯的步骤 附带相关源码 作为分享 开发环境 我使用的Qt版本是
  • ESP32 LVGL开发一 移植与例程

    简介 LVGL 轻量级和通用图形库 是一个免费和开源的图形库 提供UI通信元素的构建接口与较低资源实现的源码 适用于快速开发UI图形交互页面的应用 官方已经适配了ESP32硬件平台 库版本为v7 11 开箱即用 如有异议 欢迎留言指正 特性
  • java进制转换及算法

    本文主要讲各个进制转换的方法 进制转换 前言 一 说明 1 作用 2 本质 3 方法 4 场景 二 实例 1 字符串与16进制的互转 2 16进制字符串与byte数组互转 3 字符串与指定格式的byte数组互转 4 字符串与16进制互转 5
  • PC-Lint c/c++ 代码检查工具

    概述 PC Lint是GIMPEL SOFTWARE公司的一个产品 它是一个历史悠久 功能异常强劲的静态代码检测工具 它的使用历史可以追溯到计算机编程的远古时代 30多年以前 经过这么多年的发展 它不但能够监测出许多语法逻辑上的隐患 而且也
  • Linux - Ubuntu下安装node.js的方法

    1 Putty连接 安装Putty连接到Ubuntu 输入密码验证后进入Putty命令行控制台 1 1 查看Ubuntu版本 sudo uname m 如果显示i686 你安装了32位操作系统 如果显示 x86 64 你安装了64位操作系统
  • Redis的高级特性一览

    更多内容 欢迎关注微信公众号 全菜工程师小辉 公众号回复关键词 领取免费学习资料 应用场景 缓存系统 用于缓解数据库的高并发压力 计数器 使用Redis原子操作 用于社交网络的转发数 评论数 粉丝数 关注数等 排行榜 使用zset数据结构
  • ag-grid表格如何使用?

    1 自定义标题 tableHeaderCustom vue
  • 证件照片如何换背景底色,3个免费制作证件照的方法,简单易学

    在日常生活中 我们经常需要用到证件照 比如 找工作需要简历上附带有证件照 还有办理学生证 身份证也需要提交证件照 不同的平台有时候提交的要求 背景底色 大小等 也不一样 如果你不想每次都重拍 那么可以用一些工具 软件 在原来的照片上修改 也
  • smb协议详解和samba服务的配置

    理论部分 samba 基于smb协议使网络上的计算机能共享文件 samba的核心是smbd和nmbd两个守护进程 smbd 管理samba服务器上的共享目录 nmbd 进行netbios名解析 使客户端能浏览服务器的共享资源 协议端口 sm
  • 堆的用法总结

    堆 heaps 不是容器 而是一种特别的数据组织方式 堆一般用来保存序列容器 堆很重要 很多不同的计算机进程中都使用了它们 为了弄明白堆是什么 首先需要明白树是什么 因此首先说明树这种数据结构是什么 树是分层排列的元素或节点 每个节点有一个
  • Hive架构及基础知识

    1 用户接口 Client CLI hive shell JDBC ODBC java 访问 hive WEBUI 浏览器访问 hive 2 元数据 Metastore 元数据包括 表名 表所属的数据库 默认是 default 表的拥有者
  • C++多态学习(二)完整定义:什么是多态?

    多态分为静多态和动多态 1 静多态 函数重载 是一种多态现象 通过命名倾轧在编译阶段决定 故称为静多态 2 动多态 动多态 不是在编译器阶段决定 而是在运行阶段决定 故称为动多态 动多态形成的条件如下 1 父类中有虚函数 2 子类overr
  • SpringBoot使用@Async实现多线程异步

    SpringBoot使用 Async实现多线程异步 一 什么是异步 说明 在同步操作中 我们执行到添加数据库的时候 我们必须等待这个方法彻底执行完才能执行 修改数据 完成后 发送短信 完成后 发送消息 等操作 如果插入数据库这个动作执行时间
  • 全新防火墙6.0 单条PPPOE(ADSL)上网配置

    一 组网需求 外网接口使用ADSL拨号 内网为192 168 1 0 24网段 实现基本上网功能 二 网络拓扑 三 配置要点 1 配置接口 wan1口 接ADSL的接口 务必勾选 从服务器重新获得网关 这样ADSL拨号成功后设备会自动生成默
  • 软件工程面试——数据库

    数据库实体的关系 数据库中的实体关系指的是不同实体之间的相互依赖和联系 实体关系是数据库设计中非常重要的一个概念 它是用于描述不同实体之间的关系 连接和交互方式的 在数据库中 一个实体通常指的是一个对象或者一个概念 比如一个人 一个订单或者
  • powerdesigner如何生成数据库表

    1 建立逻辑数据模型 2 构建基础模板 3 转为PDM 4 生成sql文件 数据库设计的步骤是什么
  • C++11新关键字noexcept、override、final把我们的心意告诉编译器

    noexcept告诉编译器不抛异常 异常时一定要处理的 如果一个函数出现异常 它内部不对该异常做处理 异常会一直往上传递 给函数的调用者 到最后一直没有被处理 程序就会终止 调用std terminate 它默认调用std abort vo
  • 以太坊交易信息及event、input、logs、topics等概念机制

    文章目录 一 交易信息获取 1 1 合约事件例子定义 1 2 以太坊交易获取 二 input解析 2 1 input内容解析 2 2 input处理逻辑 三 logs解析 3 1 logs解析代码 四 topics 4 1 概念 4 2 i
  • C++拷贝构造函数

    目录 前言 一 拷贝构造函数 1 概念 2 笔试题 拷贝构造的次数 3 特征 1 拷贝构造函数是构造函数的一个重载形式 2 拷贝构造函数的参数只有一个且必须是类类型对象的引用 使用传值方式编译器直接报错 因为会引发无穷递归调用 那怎么理解无