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

1.C++ 动态内存分配对比:malloc/free VS new/delete以及 2.nullptr VS NULL 区别

1.C++ 动态内存分配对比

在 C++ 中,malloc/freenew/delete 都可以用于动态内存分配,但它们有显著的区别。以下是它们在多个维度的对比,并附带示例说明。

特性malloc/freenew/delete
类型安全❌ 需要显式类型转换✅ 类型安全,自动推导类型
构造/析构函数❌ 不会调用构造或析构函数✅ 会调用构造函数和析构函数
返回值类型void*,需要强转返回具体类型指针,无需转换
错误处理机制分配失败返回 nullptr默认抛出 std::bad_alloc,可用 nothrow 方式改为返回 nullptr
多态支持❌ 无多态性,释放对象不会触发虚析构✅ 支持多态,虚析构函数可正确调用
内存释放方式free(p)delete p(或 delete[] p
数组分配支持❌ 需要手动计算内存大小✅ 使用 new Type[n] 分配,自动构造 n 个对象
内存分配与释放对应性必须使用 free 释放由 malloc 分配的内存必须使用 delete 释放由 new 分配的内存

1. 类型安全

malloc/free:

需要显式类型转换,不具备类型安全。

int* p = (int*)malloc(sizeof(int)); // 需要强制类型转换

new/delete:

类型安全,自动推导类型。

int* p = new int; // 类型自动推导

2. 构造与析构函数调用

malloc/free:

不会调用构造函数或析构函数。

class Test {
public:Test() { std::cout << "构造函数\n"; }~Test() { std::cout << "析构函数\n"; }
};Test* t = (Test*)malloc(sizeof(Test)); // 不会输出任何信息
free(t); // 也不会调用析构函数

new/delete:

自动调用构造函数和析构函数。

Test* t = new Test(); // 输出:构造函数
delete t;             // 输出:析构函数

3. 返回值类型

malloc/free:

返回 void*,需要强制转换。

int* p = (int*)malloc(sizeof(int));

new/delete:

返回具体类型指针,无需转换。

int* p = new int;

4. 错误处理机制

malloc/free:

分配失败返回 nullptr,需要手动判断。

int* p = (int*)malloc(sizeof(int));
if (!p) {// 处理错误
}

new/delete:

默认抛出 std::bad_alloc 异常,但可通过 nothrow 返回 nullptr

try {int* p = new int;
} catch (std::bad_alloc& e) {std::cout << "分配失败: " << e.what() << "\n";
}int* p = new (std::nothrow) int;
if (!p) {// 分配失败
}

5. 多态支持

malloc/free:

不支持多态,虚析构函数不会调用。

class Base {
public:virtual ~Base() { std::cout << "Base析构\n"; }
};
class Derived : public Base {
public:~Derived() { std::cout << "Derived析构\n"; }
};Base* obj = (Base*)malloc(sizeof(Derived));
free(obj); // 不调用析构函数

new/delete:

支持多态,虚析构函数能正常调用。

Base* obj = new Derived();
delete obj; // 正确调用 Derived 和 Base 的析构函数

6. 内存释放方式

malloc/free:

使用 free(p)

int* p = (int*)malloc(sizeof(int));
free(p);

new/delete:

使用 delete pdelete[] p

int* p = new int;
delete p;

7. 数组分配支持

malloc/free:

手动计算大小,无构造函数支持。

int* arr = (int*)malloc(sizeof(int) * 10);
free(arr);

new/delete:

使用 new Type[n],支持自动构造每个对象。

int* arr = new int[10];
delete[] arr;

8. 内存分配与释放必须对应

malloc/free:

必须配对使用。

int* p = (int*)malloc(sizeof(int));
free(p); // OK
// delete p; // 错误!

new/delete:

也必须配对使用。

int* p = new int;
delete p; // OK
// free(p); // 错误!

2nullptr vs NULL

nullptrNULL 都表示“空指针”,但它们的底层机制、类型安全性和推荐用法在 C++ 中是有差别的,尤其是在现代 C++(C++11 以后)中:


✅ 简明对比:nullptr vs NULL

比较点nullptrNULL
所在语言只在 C++ 中(从 C++11 起)C 和 C++ 都有
类型std::nullptr_t通常是 0(void*)0
类型安全✅ 类型安全(不会误配)❌ 可能引起重载歧义
推荐程度✅ 强烈推荐在 C++ 中使用仅建议在 C 中使用
兼容函数重载✅ 正确调用指针版本❌ 可能调用错误的重载版本

📌 示例:看出区别的关键例子

🎯 示例 1:重载歧义

void f(int);
void f(char*);f(NULL);     // ⚠️ 可能调用 f(int),不是你想要的!
f(nullptr);  // ✅ 一定调用 f(char*),因为类型安全
  • NULL 是个整数常量(通常是 0),所以可能匹配到 int 版本。
  • nullptr 是一个专门的空指针类型,不可能匹配 int,只能匹配指针。

🎯 示例 2:类型检查

int* p = nullptr;  // ✅ OK
int* q = NULL;     // ⚠️ 也行,但是隐式从 int 转指针

✅ 总结:什么时候用哪个?

场景推荐用法
写 C++ 代码nullptr
写 C 代码NULL
写 C++ 98/03NULL(但注意类型风险)

相关文章:

  • python环境使用conda,conda如何升级默认的python版本
  • Spring集合注入Bean
  • 从项目真实场景中理解二分算法的细节(附图解和模板)
  • C++ 快速幂算法
  • 记录学习的第三十天
  • 配置openjdk调试环境
  • AI大模型-window系统CPU版安装anaconda以及paddle详细步骤-亲测有效
  • 【Spring】AutoConfigureOrder与Order注解的区别与使用方式
  • 人工神经网络学习——前馈神经网络的反向传播算法(待完善
  • Python简介与入门
  • Git,本地上传项目到github
  • 力扣每日打卡17 49. 字母异位词分组 (中等)
  • 【STM32单片机】#11 I2C通信(软件读写)
  • Sharding-JDBC 系列专题 - 第七篇:Spring Boot 集成与 Sharding-Proxy 简介
  • Spark2 之 memorypool
  • 417. 太平洋大西洋水流问题
  • 小程序 日历选择 支持前后月份切换
  • C++中的引用:深入理解与实用示例
  • 【DeepSeek 学习推理】Llumnix: Dynamic Scheduling for Large Language Model Serving
  • 实验七 ADC0804 数字电压表
  • 西湖大学本科新增临床医学专业,今年本科招生专业增至8个
  • 山西一国道塌陷致2死后续:地质雷达检测出10处道路病害
  • 重返母校:哈佛大学医学院博士后陈则宇入职北大基础医学院
  • 俄方因复活节停止战斗行动,外交部:乐见一切通往停火的努力
  • 人均300+的日料,是后厨拆开的预制料理包
  • 成功卫冕!孙颖莎4比0战胜蒯曼,获澳门世界杯女单冠军