如果你是Java、C#、PHP程序员,那么会对 new 非常熟悉,在这些编程语言中,只能通过 new 来创建对象。

在C++中,你可以像定义变量一样来创建对象,如:

  1. Student stu; //对象已被实例化,已分配内存空间,可以使用了
  2. stu.say(); //调用成员函数

这种情况下,系统会在栈区为对象分配内存。栈区是内存中的一块区域,由系统自动分配和释放,程序员无法操控,一般用来存放函数的参数值、局部变量、局部对象等。

当发生函数调用时,系统将函数参数、局部变量、局部对象依次压入栈区;函数执行结束,再按照先进后出的原则将它们弹出(销毁)。

对于大部分程序,这不会有什么问题。但当你希望在函数调用结束前销毁对象时,你是无能为力的。或者你希望通过 for 循环来创建多个对象,这种方法同样也做不到。

这个时候 new 和 delete 就派上了用场:使用 new 创建的对象,可以在任意时刻通过 delete 销毁,而且只需要一个指针指向它。

以前面的 Student 类为例,可以这样来动态创建对象:

new Student;

也可以使用构造函数:

new Student("小明", 15, 90.5f);

这样,就在堆区为对象分配了内存,并调用了构造函数。

但是此时程序员还无法访问这个对象,因为这个对象既没有名字,也没有指针指向它。这种对象称为 匿名对象 ,它确实存在,但无法访问。

用一个指针来指向Student类的对象:

Student *pStu;
pStu = new Student("小明", 15, 90.5f);

或者:

Student *pStu = new Student("小明", 15, 90.5f);


当不再需要对象时,可以通过 delete 销毁:

delete pStu;

这样,就释放掉了对象占用的内存,并调用了析构函数。

需要说明的是:new 在堆区为对象分配内存。与栈区不同的是,堆区内存由程序员分配和释放,系统不会自动销毁,即使函数调用结束了,仍然会保留堆区内存。如果程序员不主动回收堆区内存,那么只能在程序运行结束后由操作系统回收。

为了避免内存泄露,强烈建议 new 和 delete 成对出现,及时销毁不再需要的对象。

例如,下面的代码会造成严重的内存泄露:

  1. #include <iostream>
  2. #include <cstdlib>
  3. using namespace std;
  4. class Demo{
  5. private:
  6. double n;
  7. double m;
  8. int i;
  9. };
  10. void func(){
  11. Demo *p = new Demo;
  12. }
  13. int main(){
  14. int i;
  15. for(i=1; i<=1000000; i++){
  16. func();
  17. }
  18. system("pause");
  19. return 0;
  20. }

当程序运行到 system("pause"); 语句时,你可以打开任务管理器,会发现这个小小的程序竟然占用了 32M 内存。

这是因为每次调用 func 函数,都会创建一个对象,并用 p 指向它。函数运行结束,仅仅释放了指针变量 p 占用的内存,而没有释放 p 所指向的对象占用的内存。

如果在 func 函数中不回收对象内存,那么你将永远无法回收,只能等到程序运行结束由操作系统回收,这就是典型的内存泄露。

另外注意,C语言中的 malloc、free 函数不能用来为对象分配和释放内存。请看下面的例子:

  1. #include <iostream>
  2. using namespace std;
  3. class Demo{
  4. public:
  5. Demo();
  6. ~Demo();
  7. };
  8. Demo::Demo(){
  9. cout<<"Constructor"<<endl;
  10. }
  11. Demo::~Demo(){
  12. cout<<"Destructor"<<endl;
  13. }
  14. int main(){
  15. cout<<"------new------"<<endl;
  16. Demo *p1 = new Demo; //创建一个对象
  17. Demo *p2 = new Demo[5]; //创建一组对象
  18. cout<<"------malloc------"<<endl<<endl;
  19. Demo *p3 = (Demo*)malloc(sizeof(Demo));
  20. cout<<"------delete------"<<endl;
  21. delete p1; //销毁一个对象
  22. delete[] p2; //销毁一组对象
  23. cout<<"------free------"<<endl;
  24. free(p3);
  25. return 0;
  26. }

运行结果:
------new------
Constructor
Constructor
Constructor
Constructor
Constructor
Constructor
------malloc------

------delete------
Destructor
Destructor
Destructor
Destructor
Destructor
Destructor
------free------

从程序运行结果可以看出:malloc 虽然分配了内存,但没有调用构造函数;free 虽然释放了内存,但也没有调用析构函数。

C++类和new、delete操作符和堆和栈内存的分配相关推荐

  1. RT-Thread中堆和栈内存的分配

    在嵌入式软件开发中,我们经常会提到堆和栈,实际上堆和栈都是RAM上的物理内存空间,只是使用方式不同而已.栈和堆都是单片机RAM中一段连续的存储空间,该段空间一般在启动文件或链接脚本中指定,最后在C库的 ...

  2. Cherno C++系列笔记17——P52~P54 处理多返回值、模板、堆和栈内存的比较

    文章目录 1.P52 处理多返回值 2.P53 模板 2.1.模板函数 2.2.模板类 2.2.1.将数组大小作为模板参数 2.2.2.将数组大小和数组类型都作为模板参数 2.3.何时使用模板 3.P ...

  3. Linux如何在栈上分配内存,Java堆与栈内存分配及String小记

    栈内存 堆内存 基础类型,对象引用(堆内存地址) 由new创建的对象和数组, 存取速度快 相对于栈内存较慢 数据大小声明周期必须确定 分配的内存由Java虚拟机自动垃圾回收器管理.动态分配内存大小 共 ...

  4. 堆和栈内存的比较 in C++【C++学习笔记】

    54堆和栈内存的比较 in C++ 当我们的程序开始的时候,程序被分成了一堆不同的内存区域,除了堆和栈以外,还有很多东西,但我们最关心这两个

  5. C语言程序里全局变量、局部变量、堆、栈内存地址分配

    C语言程序里全局变量.局部变量.堆.栈内存地址分配 1 名词解读 2 基于ubuntu编程,调试验证 2.1 编写文件 2.2 结果分析 3 基于stm32编程,调试验证 3.1 编写代码 3.2 运 ...

  6. c++中堆、栈内存分配

    转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stac ...

  7. c++中堆、栈内存分配概念示例讲解

    首先来看看主要有几种程序内存分配: 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stack)- 由编译器自动分配释放 ,存放函数参数值,局部变量值等.其操作方式类似于数据结构中栈. 2 ...

  8. python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存

    最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...

  9. C++基础学习7:new/delete操作符

    在C语言中,动态分配和释放内存的函数是malloc.calloc和free,而在C++语言中,new.new[].delete和delete[]操作符通常会被用来动态地分配内存和释放内存.需要注意的是 ...

最新文章

  1. 3人小公司1年的创业成本
  2. 第十一届蓝桥杯校内赛题解
  3. 夏普深陷亏损 郭台铭何以执著寻求“联姻”?
  4. django(models)视图与html 简单的操作
  5. 快速上手用Python搭建自己的第一个pyecharts图表
  6. smooth_L1_loss_layer.cpp:28] Check failed: bottom[0]-channels() == bottom[1]-channels() (12 vs. 84
  7. 5年前面试题引发的“血案”(番外篇)(总结和乱侃)
  8. 通过异常捕获判断字符串是不是数字格式
  9. 项目的ar指什么_AR眼镜显示测评标准解读——概述
  10. 别学了!这 5 种即将消亡的编程语言
  11. ios蓝牙开发(三)app作为外设被连接的实现
  12. 计算机单招语文试题,2019年高职单招语文模拟试题
  13. easyui 扩展tree 获取选中节点的级数
  14. u-blox gps 串口驱动安装恢复解决方案
  15. 最短路问题——spfa算法
  16. 输出100以内的质数
  17. golang 腾讯通用OCR 文字识别 Api 调用
  18. 实验3:利用SVM实现线性高斯分类
  19. ESP8266-Arduino编程实例-HDC1080温度湿度传感器驱动
  20. esp8266之红外报警

热门文章

  1. C#中使用jieba.NET、WordCloudSharp制作词云图
  2. Scott Hanselman 喊你来看看最新的极简APII
  3. 常用加解密工具集合|视频图片加解密方案
  4. 后宫佳丽三千,假如古代皇帝也懂负载均衡算法...
  5. dotnet core 应用是如何跑起来的 通过自己写一个 dotnet host 理解运行过程
  6. WPF 从 .net core 3.1 到 .net 5.0
  7. 基于Prometheus和Grafana打造业务监控看板
  8. WeihanLi.Npoi 1.7.0 更新介绍
  9. 微软将中止支持 .NET Core 2.2,建议开发者升级至 .NET Core 3.1
  10. 在ASP.NET Core中编写合格的中间件