C++类与对象(拷贝与类的内存管理)

感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步

个人主页:LaNzikinh-CSDN博客

文章目录

  • 前言
  • 一.对象的动态建立和释放
  • 二.多个对象的构造和析构
  • 三.深拷贝与浅拷贝
  • 四.C++类的内存管理
  • 总结

前言 

我们前面讲起了一些关于C++中类与对象的一些语法,构造函数C构函数初始化成员列表等等,也讲了面对对象的程序设计方法和面对过程的程序设计方法有什么区别,我们这次就主要针对类与对象的拷贝和一些存储内存的角度继续了解


一.对象的动态建立和释放

我们在C语言中动态开辟内存和释放内存,用用到的就是malloc函数和free函数,当然在C++中也是可用的,但是来到了C++,我们就要用C++的语法,在这个地方我们主要是用new和delete来动态建立和释放。

new和delete都是运算符,不是库函数,不需要单独添加头文件,而我们malloc和free都需要头文件,而且是函数,有函数的调用就要开辟栈空间,所以而运算符是不需要的,所以说这也体现的C++的好处

格式:
new
1、类型指针 指针变量名 = new 类型
2、类型指针 指针变量名 = new 类型(初始值)
3、类型指针 指针变量名 = new 类型[元素个数]
delete
1、delete 指针变量名
2、delete[] 指针变量名

int main()
{//在堆上申请一个int类型大小的空间,并且将申请的空间初始化为10int* p1 = new int(10);delete p1;//在堆上申请4个int类型大小的空间,并没初始化int* p2 = new int[4];delete[4] p2;//在堆上申请一个Box类型大小的空间,会构造对象出来Box* p3 = new Box;delete p3;//在堆上申请4个Box类型大小的空间,会构造对象出来Box* p4 = new Box[4];delete[4] p4;return 0;
}

注意

new和delete是运算符,不是函数,因此执行效率高。虽然为了与C语言兼容,C++仍保留malloc和free函数,但建议用户不用malloc和free函数,而用new和delete运算符。new/delete 和 malloc/free有何取别呢?

1、malloc/free为C的标准库函数,new、delete则为C++的操作运算符
2、new能自动计算需要分配的内存空间,而malloc需要手工计算字节数
3、new与delete直接带具体类型的指针,malloc和free返回void类型的指针。
4、new类型是安全的,而malloc不是。例如int*p = new float[2];就会报错;
而int p = malloc(2sizeof(int))编译时编译器就无法指出错误来。
5、new调用构造函数,malloc不能;delete调用析构函数,而free不能
6.new/delete是操作符可以重载,malloc/free则不能

二.多个对象的构造和析构

我们之前学了析构函数和构造函数,但是有没有想过在多个对象中析构和构造的调用顺序是怎么样的呢?

注意:1.当类中的成员变量为另一个类的实例化对象时,我们称这个对象为成员对象。2.成员变量虽属的类中没有实现无参的构造函数是需要使用初始化成员列表。

#include<iostream>
using namespace std;
class ABC
{
public:ABC(int A, int B, int C){cout << "ABC(int A, int B, int C)" << endl;}~ABC(){cout << "~ABC()" << endl;}
private:int a;int b;int c;
};
class myD
{
public:myD() :abc1(1, 2, 3), abc2(3, 5, 7){cout << "myD()" << endl;}~myD(){cout << "~myD()" << endl;}private:ABC abc1;ABC abc2;
};
int main()
{myD a;return 0;
}

调用顺序

最开始先是构造成员对象,所以先调用成员对象所对应的构造函数,然后就是构造函数本身,最后是析构函数,析构函数的调用顺序与构造相反,总之就是先构造成员对象,在构造本身,析构相反

三.深拷贝与浅拷贝

3.1拷贝构造函数

当使用已经构造好的对象t1,初始化一个新的对象就会调用拷贝构造函数

//拷贝构造函数
Test(const Test& t)
{cout << "Test(const Test& t)" << endl;
}

3.2对象的赋值

思考这样的赋值对吗?

#include<iostream>
using namespace std;
class Test
{
public:int x;int y;int* sum;Test(int a, int b):x(a),y(b){sum = new int[4];}//拷贝构造函数Test(const Test& t){cout << "Test(const Test& t)" << endl;x = t.x;y = t.y;sum = t.sum;}~Test(){delete[4] sum;}
};
int main()
{Test t1(10,20);t1.sum[0] = 10; t1.sum[1] = 11; t1.sum[2] = 12; t1.sum[3] = 13;Test t2 = t1;
}

答案是不对的,不可以直接这样赋值会出现问题,为什么呢?因为他们的sum的地址都指向同一个地方。这个赋值并没有开辟两个空间,而是让这两个成员变量都指向了同一个区域。调用析构函数的时候会释放两次,因此就会造成问题

这个就是拷贝错误,拷贝分为浅拷贝和深拷贝,同一类对象之间的负值一般是没有副作用的,但是类中有指针,并且指针指向的动态分配的内存空间时会导致两个对象的指针指向同一块内存空间,遇到这种情况时浅拷贝,他就不能解决问题,我们就要用深拷贝去解决

class Test
{
public:int x;int y;int* sum;Test(int a, int b):x(a),y(b){sum = new int[4];}//拷贝构造函数Test(const Test& t){cout << "Test(const Test& t)" << endl;x = t.x;y = t.y;//浅拷贝//sum = t.sum;//深拷贝sum = new int[4];for (int i = 0; i < 4; i++){sum[i] = t.sum[i];}}~Test(){delete[4] sum;}
};

3.3浅拷贝

1、同一类型的对象之间可以赋值,使得两个对象的成员变量的值相同,两个对象仍然是独立的两个对象,这种情况被称为浅拷贝
2、一般情况下,浅拷贝没有任何副作用,但是当类中有指针,并且指针指向动态分配的内存空间,将导致两个对象的指针变量向同一块内存空间,当两个对象被销毁时调用析构函数,因为在析构函数中会释放指针所指向的堆空间,造成同一块堆空间被释放两次从而导致程序运行出错。
3、如果我们没有实现拷贝构造函数,C++编译器会自动实现一个拷贝构造函数,我们称之为默认拷贝构造函数,但是在默认拷贝构造函数中实现的时浅拷贝

3.4深拷贝

实现拷贝构造函数,在拷贝构造函数中需要对对象中的指针变量进行单独的内存申请。两个对象中的指针变量不会指向同一块内存空间,然后再将右值对象指针所指向的空间中的内容拷贝到新的对象指针所指向的堆空间中。

四.C++类的内存管理

C++类和对象中成员变量和成员函数是分开存储的,成员变量:静态成员变量存储于全局数据区中普通成员变量存储于函数中与结构体变量有相同的字节对其方式。成员函数:存放于代码段

证明:

#include<iostream>
using namespace std;
class C1
{
public:int i;int j;int k;
};
class C2
{
public:int i;int j;int k;int getK(){return k;}void setK(int val){k = val;}
};int main()
{C1 c1;C2 c2;cout << sizeof(c1) << endl;cout << sizeof(c2) << endl;
}

4.2this指针

this指针的本质--指针常量,当形参和成员变量同名时,可用this指针来区分

using namespace std;
class ABC
{
public:int x, y, z;ABC(int x, int y, int z){x = x;y = y;z = z;}
};
int main()
{ABC a(1, 2, 3);return 0;
}

经过编译

this指针指向调用该成员函数的对象

class ABC
{
public:int x, y, z;ABC(ABC*const this,int x, int y, int z){this->x = x;this->y = y;this->z = z;}
};
int main()
{//&a就是this指针ABC a(&a,1, 2, 3);return 0;
}

4.3类的静态成员变量

如果我要记录一个农场里面羊的数量,我该如何写呢?如果用C语言来写的话,就是面对过程的编程只有有样出生我就++,有羊死去我就减减,但是麻烦的是每个羊他可能会有年龄名字就会非常的繁琐,但是如果你是用c++面对对象的编程的话,我就可以直接构造一个样的类利用构造函数和析构函数来完成这个事情,而静态成员变量可以让这个事情完成的更完美,他是什么意思呢?可以用关键字static用于声明一个类的成员,静态的成员提供了一个同类对象的共享机制

#include<iostream>
using namespace std;
class sheep
{
public:int age;char name[32];sheep(){cnt++;}~sheep(){cnt--;}static int cnt;
};int sheep::cnt = 0;
int main()
{return 0;
}

static int cnt;只是声明了一个静态成员变量,不是内或者对象的成员变量,但是他的作用与在内和这些类的所有实例化对象中

int sheep::cnt = 0;定义了sheep这个类中的静态成员变量cnt,并初始化为零,如果不初始化默认为4

4.4类的静态成员函数

定义:使用static修饰的成员函数叫做静态成员函数

在静态成员函数内,不能访问除静态成员函数以外的其他成员变量

什么时候可以将函数设计成静态成员函数?

函数的行为跟类的实例无关,只跟类有关

静态成员函数的用处:

1.访问被private/protected修饰静态成员变量
2.可以实现某些特殊的设计模式:如Singleton(单例模式)
3.可以封装某些算法,比如数学函数,如In,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好,比如定义一个数学函数类Math。


总结

这次我们主要讲解了对象的动态开辟和释放对比C语言的不同,和前面所讲到的析构和构造的一个升华,是多对象的析构和构造,还讲了C++独特的浅拷贝和深拷贝以及C++类的一些内存管理如类的静态成员变量静态成员函数和this指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/348541.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java学生考勤管理系统

学生考勤管理系统 学生考勤管理系统。功能&#xff1a;登录&#xff0c;班级管理&#xff0c;课程管理&#xff0c;用户管理&#xff0c;课程表管理&#xff0c;个人信心&#xff0c;修改密码。 技术&#xff1a;java&#xff0c;ssh&#xff0c;struts&#xff0c;spring&…

网络安全等级保护基本要求 第1部分:安全通用要求

基本要求 第三级 安全物理环境 物理位置选择 a) 机房场地应选择在具有防震、防风和防雨等能力的建筑内&#xff1b; b) 机房场地应避免设在建筑物的顶层或地下室&#xff0c;否则应加强防水和防潮措施 物理访问控制 a) 机房出入口应配置电子门禁系统&#xff0c;控制、鉴…

Day25 首页待办事项及备忘录添加功能

​ 本章节,完成首页待办事项及备忘录添加功能 一.修改待办事项和备忘录逻辑处理类,即AddMemoViewModel和AddTodoViewModel 在 AddMemoViewModel逻辑处理类中,为了支持与其关联的View视图文件的数据绑定,需要定义一个与视图文件相匹配的实体类 Model。这个Model将包含 View中…

游戏报错steam_api.dll丢失怎么解决?steam_api.dll缺失的7种靠谱解决方法

steam_api.dll 是一个由 Valve Corporation 开发的动态链接库文件&#xff0c;专门用于其 Steam 游戏平台。这个文件是 Windows 操作系统下的一个重要组件&#xff0c;它确保了通过 Steam 平台发布的游戏能够正常运行&#xff0c;并且能够使用 Steamworks API 提供的各种功能。…

【权威出版/稳定检索】2024年气象应用、勘查与灾害应急国际会议(AEMT 2024)

2024 International Conference on Meteorological Applications, Exploration, and Disaster Emergency Response 2024年气象应用、勘查与灾害应急国际会议 【会议信息】 会议简称&#xff1a;AEMT 2024 大会时间&#xff1a;请查看官网 截稿时间&#xff1a;点击查看 大会地…

WEB漏洞 | 常见漏洞详解与思路技巧!

一、登录框常见漏洞 1、常规漏洞 sql注入、万能密码 我们在用户名中输入 ‘or 11#&#xff0c;密码随意。 就变成了select name.passwd from users where username ‘’ or 11#’ and password。 在SQL语法中 # 是注释符&#xff0c;所以后面的语句都会杯注释掉&#xff0c;那么…

更适合工程师和研究僧的FPGA专项培训课程

各位编程精英er~ 社区打造的FPGA工程师培训班上线后&#xff0c;有不少同学后台私信询问&#xff1a;“能不能出个那种专门针对某个知识点的课程呢&#xff1f;我想针对自己的薄弱点深入学习。” 贴心如我&#xff0c;当然会满足大家的学习需求啦。本周&#xff0c;社区FPGA专…

现货黄金投资价格怎么分析 低买高卖是核心!

我们做现货黄金投资&#xff0c;总是离不开对黄金价格的分析&#xff0c;分析其实就是一种理性的思考&#xff0c;我们对现货黄金当前走势进行一番思考&#xff0c;进而判断它未来的走向&#xff0c;以此作为自己投资入场的基础。那黄金投资价格怎么分析呢&#xff1f;下面我们…

Linux系统安装ODBC驱动,统信服务器E版安装psqlodbc方法

应用场景 硬件/整机信息&#xff1a;AMD平台 OS版本信息&#xff1a;服务器e版 软件信息&#xff1a;psqlodbc 12.02版本 功能介绍 部分用户在使用etl工具连接数据库时&#xff0c;需要使用到odbc驱动&#xff0c;下面介绍下服务器e版系统中编译安装此工具的相关过程。 E…

2024COSP上海国际户外展邀您一起享受户外徒步之旅,感受低碳新生活

在现在快节奏的生活中&#xff0c;我们常常忘记了那些慢慢走过的时光。科技的快速发展让我们得以快速穿越大地&#xff0c;却也让我们失去了与自然亲密接触的机会。许多壮丽的风景&#xff0c;并不是坐在车窗后、屏幕前就能够完全领略的&#xff0c;它们需要你放慢脚步&#xf…

检查子树00

题目链接 检查子树 题目描述 注意点 树的节点数目范围为[0, 20000] 解答思路 递归判断t1和t2的val是否相同&#xff0c;如果相同&#xff0c;则继续递归判断其左右子树的值是否都相同&#xff0c;如果都相同则返回true&#xff1b;如果不相同&#xff0c;则继续递归判断t1…

OCP-042之:Oracle结构体系

1. Oracle结构体系 1.1 概述 1.1.1 版本 版本后缀所代表的含义 i:代表基于Internet架构的数据库,如9i g:代表基于grid(网格)的数据库,如11g grid的目的:降低成本,提高服务质量,简化管理 Storage Grid:ASM(automatic storage management),继承了LVM技术,Oracl…

2024 Java 异常—面试常见问题

目录 一、异常的分类 二、throw和throws都是异常处理的关键字&#xff0c;二者区别。 三、try-catch-finally 中&#xff0c;如果 catch 中 return 了&#xff0c;finally 还会执行吗&#xff1f; 四、try-catch-finally 中哪个部分可以省略&#xff1f; 五、常见的 Runti…

华媒舍:15种媒体推广普遍不正确及解决方法

做为新闻媒体推广的重要一环&#xff0c;主流媒体推广在这个时代仍然发挥着重要的作用。由于种种原因&#xff0c;大家在主流媒体推广中常常做出各种各样不正确。为了能帮助广大推广工作人员们更好地进行主流媒体推广&#xff0c;本文可能详细介绍15种常见的错误&#xff0c;并…

PMP2024年新考纲有哪些变化?

在当前复杂多变的项目管理环境中&#xff0c;项目管理从业者在各种项目环境中工作&#xff0c;会采用不同的项目方法。PMP认证试图覆盖业界所有有效的项目管理方法&#xff0c; PMP考试范围包括传统的瀑布式开发模式等预测型生命周期的项目管理方法&#xff0c;也会考察敏捷或混…

[SWPUCTF 2022 新生赛]ez_1zpop(php反序列化之pop链构造)

[SWPUCTF 2022 新生赛]ez_ez_unserialize <?php class X {public $x __FILE__;function __construct($x){$this->x $x; }function __wakeup(){if ($this->x ! __FILE__) {$this->x __FILE__; }}function __destruct(){highlight_file($this->x);//flag is…

一文讲清:生产报工系统的功能、报价以及如何选择

最近这几年&#xff0c;企业越来越注重生产的速度和成本&#xff0c;尤其是“性价比”&#xff0c;生产报工系统已经变成了制造业里不可或缺的一部分。不过&#xff0c;市场上生产报工系统的选择太多&#xff0c;价格也都不一样&#xff0c;这就给很多企业出了个难题&#xff1…

使用QT绘制简单的动态数据折线图

两个核心类时QChart和QLineSeries 下面这个示例代码中&#xff0c;定时器每隔一段时间将曲线图中的数据点向右移动 一个单位&#xff0c;同时调整横坐标轴的范围&#xff0c;实现了一次滚动对应移动一个数据点的效果。 QLineSeries最多容纳40961024个点 #include <QtWidg…

《人人都是产品经理》笔记1:什么是产品?怎么入行?

《人人都是产品经理》笔记1&#xff1a;什么是产品&#xff1f;怎么入行&#xff1f; 产品是什么&#xff1f;产品经理、产品管理&#xff1f;真的想做产品经理吗&#xff1f;全书结构示意图 从写这篇文章开始&#xff0c;是个人第二次对该书进行阅读&#xff0c;在此进行个人的…

Codeforces Global Round 26 E. Shuffle 【换根DP】

E. Shuffle 题意 给定一颗 n n n 个节点的树 T T T&#xff0c;现在要求恰好执行下面的程序操作一次&#xff1a; 从 T T T 中选择一个点&#xff0c;作为 T 2 T_2 T2​ 的新根节点将这个点从 T T T 中删除&#xff0c;现在 T T T 被分成了一个或一个以上的连通块树对每…