new语法
在C++中,new
是用于动态内存分配的操作符,允许在运行时请求内存空间。以下是 new
的完整语法和用法说明:
1. 基本语法
1.1 单一对象分配
type* pointer = new type(initializer);
- 作用:分配一个
type
类型的对象,并返回指向该对象的指针。 - 初始化:
- 若省略
(initializer)
,对象默认初始化(基本类型值未定义,类类型调用默认构造函数)。 - 使用
()
进行值初始化(基本类型初始化为0,类类型调用默认构造函数)。 - 使用
(value)
进行直接初始化。
- 若省略
示例:
int* p = new int(42); // 初始化为42
std::string* s = new std::string("hello"); // 调用string构造函数
double* d = new double(); // 值初始化为0.0
1.2 数组分配
type* array = new type[size]; // 分配size个元素的数组
- 初始化:
- 基本类型元素值未定义。
- 使用
new type[size]()
进行值初始化(所有元素为0或默认值)。
示例:
int* arr = new int[5]; // 未初始化的数组
int* arr2 = new int[5](); // 所有元素初始化为0
std::string* strs = new std::string[3]; // 调用3次string默认构造函数
1.3 多维数组分配
对于二维数组,常见两种方式:
// 方法一:非连续内存(指针数组)
int** matrix = new int*[rows];
for (int i = 0; i < rows; i++) {matrix[i] = new int[cols];
}// 方法二:连续内存
int* matrix = new int[rows * cols]; // 手动计算索引
2. 定位new(Placement New)
允许在已分配的内存块上构造对象:
void* memory = operator new(sizeof(type)); // 分配原始内存
type* obj = new(memory) type(initializer); // 在memory上构造对象
- 用途:自定义内存管理、实现内存池等。
- 注意:需手动调用析构函数,不释放内存:
obj->~type(); // 手动调用析构函数
3. 初始化方式对比
语法 | 效果 |
---|---|
new int | 默认初始化(值未定义) |
new int() | 值初始化(0) |
new int(42) | 直接初始化为42 |
new int[5] | 数组元素默认初始化(值未定义) |
new int[5]() | 数组元素值初始化为0 |
new int[5]{1,2} | 列表初始化(C++11+,剩余元素补0:{1,2,0,0,0} ) |
4. 异常处理
- 内存不足:默认情况下,若内存分配失败,
new
抛出std::bad_alloc
异常。 - 不抛异常版本:使用
std::nothrow
参数,失败时返回nullptr
:int* p = new (std::nothrow) int; if (p == nullptr) {// 内存分配失败处理 }
5. 与 delete
的配对使用
- 单一对象:使用
delete
:int* p = new int(42); delete p; // 释放内存并调用析构函数
- 数组:使用
delete[]
:int* arr = new int[5]; delete[] arr; // 释放整个数组,必须用[]
- 定位new:手动调用析构函数,不使用
delete
:obj->~type(); // 仅调用析构函数,内存由用户管理
6. 智能指针与RAII(推荐做法)
为避免内存泄漏,优先使用智能指针管理动态内存:
#include <memory>// 单一对象
std::unique_ptr<int> p(new int(42)); // 自动释放// 数组(C++14+)
std::unique_ptr<int[]> arr(new int[5]()); // 自动释放// 使用make_unique(C++14+)
auto p2 = std::make_unique<int>(42); // 更安全的创建方式
7. 常见错误
- 内存泄漏:忘记调用
delete
或delete[]
。 - 双重释放:多次释放同一块内存。
- 悬空指针:释放内存后仍使用指针。
- 混用
delete
和delete[]
:对数组使用delete
会导致未定义行为。
总结
场景 | 语法示例 | 释放方式 |
---|---|---|
单一对象 | int* p = new int(42); | delete p; |
数组 | int* arr = new int[5]; | delete[] arr; |
定位new | T* obj = new(mem) T(); | obj->~T(); |
智能指针(单一对象) | std::unique_ptr<int> p(new int); | 自动释放 |
智能指针(数组) | std::unique_ptr<int[]> arr(new int[5]); | 自动释放 |
合理使用 new
和智能指针,遵循 RAII 原则,可有效避免内存管理问题。