C++类和对象(HM)

2024-04-05 21:20
文章标签 c++ 对象 hm

本文主要是介绍C++类和对象(HM),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1.拷贝构造函数的调用时机

2.拷贝构造函数的调用规则

3.浅拷贝和深拷贝

(1)浅拷贝

(2)深拷贝

4.初始化列表

5.类作为成员变量


1.拷贝构造函数的调用时机

我们首先要自己定义一个类:

(1)使用已知的对象初始化一个新的对象

这个相当于让已知的对象p1初始化对象p2;

(2)值传递的方式给函数的参数传值

通过打印的结果就可以发现执行了拷贝构造函数,这个是因为我们使用了值传递的方式传递对象p,实际上这两个函数里面的p并不是同一个p,编译器在调用func函数的时候会重新的拷贝一份作为副本;就是说test函数不会直接把自己的p传到func函数里面去,而是重新拷贝一份传给func函数

(3)值的方式返回局部的对象:

这个地方先调用test函数,test函数里面接着调用func函数,func函数会返回一个对象,这个对象就不会直接地返回到我们的test函数里面去 ,而是拷贝一份返回到test函数里面去,我们打印这两个对象的地址就可以发现是不一样的,这个也可以验证拷贝函数是执行了的。

2.拷贝构造函数的调用规则

(1)首先我们必须要知道的是:当我们定义了一个类以后,编译器会自动地实现至少3个函数,一个是默认的构造函数,一个是默认的析构函数,一个是拷贝构造函数(值传递);

(2)当我们自己写了一个自定义的构造函数并且使用的话,如果我们自己不写默认的构造函数,编译其实不会提供的;

(3)当我们写了拷贝构造函数但是不写默认构造函数和自定义构造函数的时候,编译器也不会提供自定义构造和默认构造函数的;

3.浅拷贝和深拷贝

(1)浅拷贝

使用编译器提供的拷贝构造函数,就是浅拷贝:

我们是使用了new在堆区上面开辟空间,把地址传递给了height指针;最后判断是否为空,不是空的话我们就释放掉,然后进行置为空指针;

因为释放是发生在程序销毁的时候,所以我们在析构的那个函数里面释放空间,但是因为定义的对象,先进去的后出来,也就是说先定义的对象后释放,所以p2先执行析构函数,释放空间,这个时候执行了堆区的空间的销毁,p1在执行析构函数,再次释放,就造成了一块空间多次释放,这个就是内存泄漏,导致程序崩溃;

浅拷贝带来的问题就是堆区空间重复释放;

(2)深拷贝

我们在原来的代码的基础上面,添加上我们自己的拷贝构造函数:

person(const person& p)
{cout << "拷贝构造函数执行中" << endl;age = p.age;//height = p.height;//这行代码是编译器默认实现的拷贝函数height = new int(*p.height);
}

原来的height = p.height;相当于是把p1的height的地址传递给了p2,这样两个就指向了同样的内存空间,所以会出现交叉多次释放的问题;

我们的解决方案就是重新开辟空间,这样p2的height就会指向新的空间(而不是原来的0x00ff48了);

这样在析构函数执行的时候,p1释放p1的空间,p2释放p2的空间,就不会出现多次释放同一块空间的问题了;----------------------这就是深拷贝。

4.初始化列表

就是提供了一种新的初始化的方法:我们原来是使用这种自定义的构造函数进行初始化:

我们现在使用的是初始化列表:就是在原来的基础上,去掉自定义构造函数的函数体,后面加冒号,写上属性(形参)这种:下面的示例,abc就是我们的属性,a1,b1,c1就是我们的形参:

5.类作为成员变量

打印结果:

这个就是想要说明:A类里面有B成员变量,B也是一个类,这个题就是person类里面有person成员变量,phone也是一个类,执行构造的时候,先执行B的构造,再执行A的构造,执行析沟的时候,先执行A的析构,后执行B的析构,就这个顺序的问题。

这篇关于C++类和对象(HM)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/878180

相关文章

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee