当前位置: 首页 > ai >正文

0901 C++的动态内存分配与回收

Part 1.梳理思维导图

一.C++的动态内存分配与回收

1.C++和C中的分配与回收

1.C语言中用的是malloc和free两个函数

2.C++可以使用这两个函数,或者使用new和delete两个关键字

2.用new来内存分配

        a.单个分配

格式:数据类型 *指针名 = new 数据类型

示例:int *p = new int;

        b.连续分配

格式:数据类型 *指针名 = new 数据类型[个数]

示例:int *p = new int[5];

3.用delete来内存回收

        a.单个回收

格式:delete 指针名

示例:delete p;

        b.连续回收

格式:delete []指针名

示例:delete []p;

4.malloc和free与new和delete的区别

1.new和delete属于关键字,而malloc和free属于函数

2.new创建堆区空间是用数据类型作为单位,而malloc是用字节作为单位

3.new申请空间是可以初始化的,而malloc不可以

4.new返回的指针的数据类型是申请空间用的数据类型,而malloc是返回万能指针

5.new和delete分单个和多个,malloc和free不分

6.new申请类对象空间时,会自动调用构造函数,而malloc不会

7.delete释放类对象空间时,会自动调用析构函数,而free不会

二.类中特殊的成员函数

1.种类

1.构造函数        2.析构函数        3.拷贝构造函数        4.拷贝赋值函数        5.移动构造函数

6.移动赋值函数        7.取地址符重载        8.常取地址符重载 

原因:1.这些成员函数,不用手动定义,系统会给,手动定义了之后,系统会取消原来的默认函数

2.这些成员函数不需要手动调用,会自动调用

2.构造函数

        a.功能

用类实例化一个对象时,会自动调用该函数,是类对象申请空间和初始化的函数

        b.格式
类名(形参列表)
{函数体内容;
}
        c.使用场景

1.在栈区时:当实例化一个类对象时,会调用构造函数

2.在堆区时:当用new给申请一个类对象空间时,会调用构造函数

        d.无参构造函数与有参构造函数

1.无参构造函数:形参列表没有任何参数,在请定义一个类对象时使用

2.有参构造函数:形参列表有参数,在初始化一个类对象时使用

#include <iostream>using namespace std;class Stu
{
private:string name;int age;double score;
public:Stu (){cout << "无参构造函数" << endl;}Stu (string name = "--",int age = 0,double score = 0){Stu::name = name;Stu::age = age;Stu::score = score;cout << "有参构造函数" << endl;}void output();
};void Stu::output()
{cout << "姓名:" << name << endl;cout << "年龄:" << age << endl;cout << "分数:" << score << endl;
}int main()
{Stu s1;Stu s2("张三",18,99);s2.output();Stu *p = new Stu();Stu *p2 = new Stu("李四",28,88);p2->output();Stu *p3 = (Stu *)malloc(sizeof(Stu));return 0;
}
        e.初始化列表
                e1.定义

在初始化一个类对象时使用,只有构造函数有初始化列表

                e2.格式
类名(形参1,形参2,形参3,...,形参n):成员变量1(形参1),成员变量2(形参2),成员变量3(形参3),...,成员变量n(形参n)
{函数体内容;
}
#include <iostream>using namespace std;class Stu
{
private:string name;int age;double score;
public:Stu (string name = "--",int age = 0,double score = 0):name(name),age(age),score(score){cout << "有参构造函数" << endl;}void output();
};void Stu::output()
{cout << "姓名:" << name << endl;cout << "年龄:" << age << endl;cout << "分数:" << score << endl;
}int main()
{Stu s1;Stu s2("张三",18,99);s2.output();Stu *p = new Stu();Stu *p2 = new Stu("李四",28,88);p2->output();Stu *p3 = (Stu *)malloc(sizeof(Stu));return 0;
}

        f.类的嵌套

1.先调用被嵌套类的构造函数

2.再调用嵌套类的构造函数

#include <iostream>using namespace std;class Score
{
private:int Chinesescore;int Mathscore;int Englishscore;
public:Score(){cout << "Score::无参构造函数" << endl;}Score(int Chinesescore,int Mathscore,int Englishscore):Chinesescore(Chinesescore),Mathscore(Mathscore), Englishscore(Englishscore){cout << "Score::有参构造函数" << endl;}
};class Stu
{
private:string name;int id;Score Sco;
public:Stu(){cout << "Stu::无参构造函数" << endl;}Stu(string name,int id,int Chinesescore,int Mathscore,int Englishscore):name(name),id(id),Sco(Chinesescore, Mathscore, Englishscore){cout << "Stu::有参构造函数" << endl;}};int main()
{Stu s1("张三",1001,99,88,77);return 0;
}

3.析构函数

        a.功能

当一个类对象结束后,需要调用析构函数来回收资源

        b.格式
~类名()
{函数体内容;
}
        c.使用场景

1.在栈区:类对象结束后,析构函数会回收资源

2.在堆区:使用delete释放类对象空间时,会调用析构函数

        d.示例
#include <iostream>using namespace std;class Time
{
private:int hour;int min;int score;
public:Time(){cout << "Time::无参构造函数" << endl;}Time(int hour,int min,int score):hour(hour),min(min),score(score){cout << "Time::有参构造函数" << endl;}~Time(){cout << this << endl;cout << "Time::析构函数" << endl;}
};int main()
{Time tm1;Time tm2(16,03,20);cout << &tm1 << &tm2 << endl;Time tm3(tm2);Time tm4 = tm3;return 0;
}
4.拷贝构造函数
        a.功能

用一个类对象给另一个类对象初始化时,会调用拷贝构造函数

        b.格式
类名(const 类名 &other)
{函数体内容;
}
        c.使用场景

1.用一个类对象给另一个类对象初始化时,会调用拷贝构造函数

2.当类对戏作为函数实参,会调用拷贝构造函数

3.函数的返回值是一个类对象的话,会调用拷贝构造函数

#include <iostream>using namespace std;class Time
{
private:int hour;int min;int score;
public:Time(){cout << "Time::无参构造函数" << endl;}Time(int hour,int min,int score):hour(hour),min(min),score(score){cout << "Time::有参构造函数" << endl;}~Time(){cout << this << endl;cout << "Time::析构函数" << endl;}Time(const Time &other):hour(other.hour),min(other.min),score(other.score){cout << "Time::拷贝构造函数" << endl;}
};int main()
{Time tm1;Time tm2(16,03,20);cout << &tm1 << &tm2 << endl;Time tm3(tm2);//类对象给另一个类对象初始化Time tm4 = tm3;return 0;
}
        d.浅拷贝和深拷贝
                d1.定义

1.浅拷贝:当使用系统默认的拷贝构造函数,就是浅拷贝

2.深拷贝:当使用程序员自己定义的特殊拷贝构造函数,就是深拷贝

                d2.为什么需要深拷贝(为什么需要自己定义拷贝构造函数)

当类成员里面有一个指针类型的成员,在使用浅拷贝时,系统默认直接赋值指针地址到新的类对象,此时两个类对象的指针成员的存储地址指向同一片区域,当有一个类对象改变时,会连带另一个类对象改变

                d3.示例
#include <iostream>using namespace std;class Time
{
private:int hour;int min;int score;int *day;
public:Time(){cout << "Time::无参构造函数" << endl;}Time(int hour,int min,int score,int day):hour(hour),min(min),score(score),day(new int(day)){cout << "Time::有参构造函数" << endl;}~Time(){delete day;day = nullptr;cout << "Time::析构函数" << endl;}
//    Time(const Time &other):hour(other.hour),min(other.min),score(other.score),day(other.day)
//    {
//        cout << "Time::浅拷贝构造函数" << endl;
//    }Time(const Time &other):hour(other.hour),min(other.min),score(other.score),day(new int(*(other.day))){cout << "Time::深拷贝构造函数" << endl;}
};int main()
{Time tm1;Time tm2(16,03,20,1);cout << &tm1 << &tm2 << endl;Time tm3(tm2);Time tm4 = tm3;return 0;
}

Part 2.习题

设计一个Per类,类中包含私有成员:姓名、年龄、指针成员身高、体重,再设计一个Stu类,类中包含私有成员:成绩、Per类对象p1,设计这两个类的构造函数、析构函数和拷贝构造函数。

#include <iostream>using namespace std;class Per
{
private:string name;int age;double *high;double weight;
public:Per(string name,int age,double high,double weight):name(name),age(age),high(new double(high)),weight(weight){cout << "Per::有参构造函数" << endl;}~Per(){delete high;high = nullptr;cout << "Per::析构函数" << endl;}Per(const Per &other):name(other.name),age(other.age),high(new double(*(other.high))),weight(other.weight){cout << "Per::拷贝构造函数" << endl;}void output(){cout << "姓名: " << name << ", 年龄: " << age << ", 身高: " << *high << ", 体重: " << weight << endl;}
};
class Stu
{
private:double score;Per p1;
public:Stu(double score,string name,int age,double high,double weight):score(score),p1(name,age,high,weight){cout << "Stu::有参构造函数" << endl;}~Stu(){cout << "Stu::析构函数" << endl;}Stu(const Stu &other):score(other.score),p1(other.p1){cout << "Stu::拷贝构造函数" << endl;}void output(){cout << "分数: " << score << endl;p1.output();}};int main()
{Stu s1(99,"张三",12,180,130);s1.output();Stu s2(s1);s2.output();return 0;
}

http://www.xdnf.cn/news/19493.html

相关文章:

  • 全局网络,一目了然——OpManager可视化监控全景体验
  • AI 智能体架构中的协议设计三部曲:MCP → A2A → AG-UI
  • uniApp App 嵌入 H5 全流程:通信与跳转细节拆解
  • 嵌入式ARM程序高级调试技能:22.malloc free 的wrap实现,free支持 align free
  • 【机器学习入门】5.1 线性回归基本形式——从“选西瓜”看懂线性模型的核心逻辑
  • [Java]PTA:jmu-java-01入门-基本输入
  • YOLO 目标检测:YOLOv3网络结构、特征输出、FPN、多尺度预测
  • 在 React Native 层禁止 iOS 左滑返回(手势返回/手势退出)
  • 每日算法题【二叉树】:二叉树查找值为x的节点、给定字符串用前序遍历构建二叉树、二叉树的销毁
  • Topaz Video AI:AI驱动的视频增强与修复工具
  • 如何选择单北斗变形监测系统才高效?
  • 【思考】WSL是什么
  • 深度学习环境搭建运行(一) Ubuntu22.04 系统安装 CUDA11.8 和 CUDNN8.6.0 详细步骤(新手入门)
  • AI 赋能 Java 开发效率:全流程痛点解决与实践案例(三)
  • 【先楫HPM5E00_EVK系列-板卡测评3】hpm5e00evk平台中断、定时器、PWM、USART等基础功能详解
  • NOSQL——Redis
  • Trae + MCP : 一键生成专业封面
  • @Autowired注入底层原理
  • STM32-FreeRTOS操作系统-任务创建
  • 洛谷 P5836 [USACO19DEC] Milk Visits S-普及/提高-
  • 贪心算法解决钱币找零问题(二)
  • 基于单片机倒车雷达/超声波测距设计
  • Linux->网络入门
  • 《论文阅读》从心到词:通过综合比喻语言和语义上下文信号产生同理心反应 2025 ACL findings
  • infinityfree mysql 加入数据库部分 filezilla 设备共享图片和文本不用浏览器缓存
  • 第六章 Vue3 + Three.js 实现高质量全景图查看器:从基础到优化
  • hive表不显示列注释column comment的问题解决
  • Linux signal 图文详解(二)信号发送
  • 为什么服务器接收 URL 参数时会接收到解码后的参数
  • DHT11-温湿度传感器