new创建数组本质是分配连续内存并返回首元素指针,不调用容器构造逻辑,仅对类类型逐个调用构造函数;必须用delete[]释放,否则ub;不支持直接初始化列表,推荐优先使用std::vector。

new 创建数组的基本语法和内存布局
用 new 创建数组,本质是分配一块连续内存,并返回首元素指针。它不调用容器类构造逻辑,只是原始内存分配 + 构造函数逐个调用(对类类型)。
基本写法:int* arr = new int[10]; —— 分配 10 个 int,返回 int*;MyClass* obj_arr = new MyClass[5]; —— 对每个元素调用默认构造函数。
-
new T[N]返回的是T*,不是“数组类型”,不能用sizeof获取元素个数 - 数组长度
N必须是编译期常量(C++14 及以前),C++14 起允许非常量表达式,但必须求值为正整数 - 如果
T是类类型且无默认构造函数,new T[N]编译失败
delete[] 必须配对使用,否则 UB
用 new[] 分配的内存,必须用 delete[] 释放。用 delete(不带方括号)释放会导致未定义行为(UB),常见表现为程序崩溃、内存泄漏或静默损坏。
错误示例:int* p = new int[3]; delete p; —— 危险;正确写法:delete[] p;
- 编译器通常不检查
delete/delete[]是否匹配,靠程序员自觉 - 即使
T是int或char这类 POD 类型,也必须用delete[],否则可能跳过析构逻辑(对类类型)或破坏堆管理元数据 - VS 和 GCC 在调试模式下有时会触发断言或报错,但发布版大概率静默失败
new[] 无法直接初始化非 POD 类型数组
C++ 标准不允许在 new[] 表达式中为数组元素指定初始化器(比如 new int[3]{1,2,3} 是非法的),这和栈上数组声明不同。
想初始化,得手动赋值或循环调用构造函数(对类类型)。例如:std::string* s = new std::string[2]; s[0] = "hello"; s[1] = "world";
-
new int[3]{1,2,3}在 C++11/14 中不合法,C++20 起仍不支持 —— 这不是遗漏,是标准明确禁止 - 若需初始化,推荐改用
std::vector:std::vector<int> v{1,2,3};</int>,更安全且支持初始化列表 - 对自定义类,若需特定参数初始化多个对象,
new[]无能为力,只能事后赋值或重载operator new[](极少必要)
为什么你应该优先用 std::vector 而不是 new[]
除非你在写底层库、嵌入式受限环境,或明确需要裸指针语义,否则 new[] 几乎总是比 std::vector 更容易出错、更难维护。
-
std::vector自动管理内存,异常安全,支持移动语义,还能用at()做边界检查 -
new[]分配失败抛std::bad_alloc,但没 RAII 保护,异常路径中容易漏掉delete[] - 现代编译器对
std::vector的优化极好,性能差距可忽略;而new[]多一层指针间接、少一层容量缓存、无法自动 resize
真正绕不开 new[] 的场景极少:比如对接 C API 要求传 int* + 长度,且确定生命周期简单可控;或者做内存池底层分配器。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











