在C++中,new与malloc()都可用于在堆中分配一块内存。其中,new是C++的语法,而malloc则来自古老的C语言,二者在使用时有何区别?

new会调用构造函数,而malloc()不会

假设有一个矩形类Rect,定义如下:

class Rect {
public:
Rect() {
/* 初始化矩形的宽和高为10 */
mWidth = mHeight = 10;
std::cout << "Calling Rect(): ";
display();
} Rect(float width, float height) {
/* 指定矩形的宽和高,构造一个矩形 */
mWidth = width;
mHeight = height; std::cout << "Calling Rect(float, float): ";
display();
} ~Rect() {
/* 析构函数 */
std::cout << "Calling ~Rect(): ";
display();
} void display() {
/* 输出矩形信息,最后会额外输出一个换行符 */
std::cout << "Rect(" << mWidth << ", " << mHeight << ")\n";
} private:
float mWidth; // 矩形的宽
float mHeight; // 矩形的高
};

这个类的实现很简单,唯一需要注意的地方在于构造函数和析构函数内都有一条输出,便于我们了解程序是否调用了相关函数。

我们的测试代码长这个样子:

int main() {
std::cout << "[INFO] malloc:\n";
auto ptrRect1 = (Rect*)malloc(sizeof(Rect));
ptrRect1->display(); std::cout << "\n[INFO] new:\n";
auto ptrRect2 = new Rect;
ptrRect2->display(); std::cout << "\n[INFO] program finish:\n";
}

编译运行后,程序的输出如下:

[INFO] malloc:
Rect(9.86058e+27, 6.30584e-43) [INFO] new:
Calling Rect(): Rect(10, 10)
Rect(10, 10) [INFO] program finish:

可以看到,调用malloc后,没有对分配的那块内存初始化,最后输出矩形的宽和高是内存中保存的随机值;而使用new分配的对象会调用构造函数初始化内存,这就是二者的区别所在。

另外还有一点,这两块在堆上分配的内存没有被回收,虽然在这个小程序中,程序运行结束后会由操作系统负责回收内存,但作为一名专业的编程人员,回收不必要的内存总是一个好习惯,而这,就需要我们考虑delete与free()的区别。

delete会调用析构函数,而free()不会

想必大家都已经猜到了,与new/malloc()的区别类似,delete相较于free, 会调用析构函数。

int main() {
auto ptrRect1 = (Rect*)malloc(sizeof(Rect));
auto ptrRect2 = new Rect; std::cout << "[INFO] free:\n";
free(ptrRect1); std::cout << "\n[INFO] delete:\n";
delete ptrRect2; std::cout << "\n[INFO] program finish:\n";
}

程序的输出如下所示:

Calling Rect(): Rect(10, 10)
[INFO] free: [INFO] delete:
Calling ~Rect(): Rect(10, 10) [INFO] program finish:

输出结果验证了我们的说法。

对象数组的分配与释放

我们已经知道,malloc/free作为C语言的底层API, 不会为我们做额外的工作,而C++中的new/delete同时承担构造/析构的工作。最后还留有一个问题,对于对象的数组,也遵循相同的规定吗?答案是肯定的,请看下面这个例子:

int main() {
std::cout << "[INFO] create 5 rects:\n";
auto rect_array = new Rect[5]; std::cout << "\n[INFO] delete rect array:\n";
delete[] rect_array;
}

输出为:

[INFO] create 5 rects:
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10) [INFO] delete rect array:
Calling ~Rect(): Rect(10, 10)
Calling ~Rect(): Rect(10, 10)
Calling ~Rect(): Rect(10, 10)
Calling ~Rect(): Rect(10, 10)
Calling ~Rect(): Rect(10, 10)

从输出中可以看到,使用new Rect[5]分配5个Rect对象时,会为5个Rect对象分别调用一次构造函数;而使用delete[]释放内存时,也会同时调用Rect对象的析构函数。

有的朋友可能好奇:如果不使用delete[] rect_array, 直接使用delete rect_array, 会发生什么呢?既然写到这里,就顺便试一试吧:

int main() {
std::cout << "[INFO] create 5 rects:\n";
auto rect_array = new Rect[5]; std::cout << "\n[INFO] delete rect array:\n";
delete rect_array;
}

我使用的clang编译器给了我一个Warning: 使用new[]分配的内存需要使用delete[]释放。但是编译能通过,最后的输出结果为:

[INFO] create 5 rects:
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10)
Calling Rect(): Rect(10, 10) [INFO] delete rect array:
Calling ~Rect(): Rect(10, 10)

因此,将delete[]换成delete后,只有第一个Rect对象被释放,程序的状态也出现了异常。

结语

最后和大家讲个笑话:我最早学C语言的时候,以为使用malloc()申请的内存,如果没有调用free()释放,这块内存就不能再用了。所以,一开始不敢使用malloc()这个函数,并且总是感觉自己电脑的内存越来越小。后来才知道,原来操作系统会在程序运行结束后回收内存,所以完全不必担心,尽管放心大胆地写,没听说谁写代码把电脑干废的。

在新一代的C++中,有智能指针这一更为高级的概念,不过这些都是后话了,有时间再研究研究。

C++中,new与malloc的区别何在?(代码实验向)的更多相关文章

  1. C++中new和malloc的区别

    原文:http://blog.163.com/ji_wei8888/blog/static/4868044620117361747282/ 1.new 是c++中的操作符,malloc是c 中的一个函 ...

  2. [转发]C++中new和malloc的区别

    原文地址:https://blog.csdn.net/linux_ever/article/details/50533149 new与malloc的10点区别 1. 申请的内存所在位置 new操作符从 ...

  3. vector中resize和reserve的区别,代码验证

    #include <vector> using namespace std; int main() { vector<int> resizeVect; vector<in ...

  4. php中urlencode与rawurlencode的区别

    前段时间说自己遇到了个<URL加号引发错误>的BUG,引起这个bug的原因就是自己在URL中使用了 urlencode 函数,该函数会把空格转换成加号,这样就导致URL解析出错,而空格只有 ...

  5. C++中new和malloc区别

    面试中new和malloc区别会被经常问到,审视了自己,发现不知道该怎么表达 整理一下: 1.从属性 new/delete是C++关键字,需要编译器支持: malloc/free是库函数,需要头文件支 ...

  6. 【转载】new和malloc的区别

    本篇随笔为转载,原贴地址:C++中new和malloc的十点区别. 前言 几个星期前去面试C++研发的实习岗位,面试官问了个问题: new与malloc有什么区别? 这是个老生常谈的问题.当时我回答n ...

  7. C语言中堆和栈的区别

    原文:http://blog.csdn.net/tigerjibo/article/details/7423728 C语言中堆和栈的区别 一.前言: C语言程序经过编译连接后形成编译.连接后形成的二进 ...

  8. java中堆和堆栈的区别

    java中堆和堆栈的区别(一) 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取 ...

  9. 转载:C++中堆和栈的区别

    C++中堆和栈的区别,自由存储区.全局/静态存储区和常量存储区     文章来自一个论坛里的回帖,哪个论坛记不得了!    在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和 ...

  10. 转 new和malloc的区别

    传送门 new和malloc的区别 1. malloc()函数 1.1 malloc的全称是memory allocation,中文叫动态内存分配. 原型:extern void *malloc(un ...

随机推荐

  1. 智能制造之 SMT 产线监控管理可视化

    前言 随着<中国制造2025>的提出,制造业迎来了全新的发展机遇.更多的企业将制造业信息化技术进行广泛的应用,如 MES 系统.数字孪生以及生产管理可视化等技术的研究应用,已经成为社会各界 ...

  2. 体验函数计算 FC 3.0,写测评赢取索尼头戴式耳机

    11月1日云栖大会,函数计算3.0全新升级,相对函数计算2.0,3.0版本突出易用性.高弹性,并且可以和更多阿里云服务无缝集成.业内首发神龙 Serverless GPU 架构,冷启动大幅优化,全链路 ...

  3. <vue初体验> 基础知识 4、 vue的生命周期

    系列导航 <vue初体验> 一. vue的引入和使用体验 <vue初体验> 二. vue的列表展示 <vue初体验> 三. vue的计数器 <vue初体验&g ...

  4. vant-list实现下拉加载更多

    1 <template> 2 <div class="home-wrapper"> 3 <div class="swipe-box" ...

  5. 信息收集-CDN绕过

    什么是CDN加速? CDN 的全称是 Content Delivery Network,即内容分发网络.CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器, 通过中心平台的负载 ...

  6. 解决xshell-ssh远程登录,只能通过public key登录导致无法登录的情况

    xshell无法通过密码登录的问题如下: 1.登录主机:vi /etc/ssh/sshd_config 2.搜索关键字:PasswordAuthentication 3.将PasswordAuthen ...

  7. appium(三)使用方法

    一.appium环境搭建(先决条件) 1.安装JDk 2.安装SDK 参考文章:https://www.cnblogs.com/mrwhite2020/p/13160994.html 3.安装appn ...

  8. KVM 核心功能:内存虚拟化

    1 内存虚拟化简介 QEMU-KVM 提供内存的虚拟化,从虚拟机角度看其自身拥有的内存就是真实的物理内存.实际上,虚拟机是 host 上的一个 qemu 进程,在为虚拟机指定内存时,host 上并没有 ...

  9. mysql 用户及用户权限管理命令总结-用户添加及添加权限

    本文为博主原创,转载请注明出处: linux 使用root 用户登录mysql 1. 添加用户,并设置用户登录密码: 格式: create user user_name@'ip'  identifie ...

  10. zookeeper 特点、使用场景及安装,配置文件解析

    本文为博主原创,未经允许不得转载: 1. Zookeeper 特点: ZooKeeper是用于分布式应用程序的协调服务.它公开了一组简单的API,分布式应用程序可以基于这些API用于同步,节点状态.配 ...