C++ new 运算符
外观
C++ new运算符是C++中用于动态内存分配的核心操作符,它允许程序在运行时从堆(heap)中请求内存空间。与C语言的malloc()
不同,new不仅分配内存,还会调用对象的构造函数,是面向对象内存管理的关键工具。
基本语法与功能[编辑 | 编辑源代码]
new运算符的基本语法如下:
pointer_variable = new data_type;
pointer_variable = new data_type[size]; // 数组分配
pointer_variable = new data_type(initial_value); // 带初始化
工作原理[编辑 | 编辑源代码]
当使用new时,会发生以下步骤:
- 计算所需内存大小
- 在堆上寻找连续可用空间
- 调用构造函数(对于类对象)
- 返回指向该内存的首地址指针
基础示例[编辑 | 编辑源代码]
单对象分配[编辑 | 编辑源代码]
#include <iostream>
int main() {
int* ptr = new int; // 分配一个int空间
*ptr = 42; // 存储值
std::cout << *ptr; // 输出: 42
delete ptr; // 必须手动释放
return 0;
}
数组分配[编辑 | 编辑源代码]
double* arr = new double[10]; // 分配10个double的数组
arr[0] = 3.14; // 访问第一个元素
delete[] arr; // 必须使用delete[]
高级特性[编辑 | 编辑源代码]
定位new(Placement new)[编辑 | 编辑源代码]
允许在已分配的内存上构造对象:
#include <new>
char buffer[sizeof(int)];
int* p = new (buffer) int(42); // 在buffer位置构造int
// 不需要delete,因为是栈内存
异常处理[编辑 | 编辑源代码]
默认情况下,new失败会抛出std::bad_alloc
异常:
try {
int* p = new int[10000000000];
} catch (const std::bad_alloc& e) {
std::cerr << "内存不足: " << e.what();
}
可以使用nothrow
版本:
int* p = new(std::nothrow) int[100];
if (!p) { /* 处理分配失败 */ }
数学原理[编辑 | 编辑源代码]
new操作的时间复杂度通常为O(1),但实际性能取决于内存分配器的实现。连续分配n个对象的空间需求为:
其中开销包括内存对齐填充和管理信息。
实际应用案例[编辑 | 编辑源代码]
动态数据结构[编辑 | 编辑源代码]
实现链表节点分配:
struct Node {
int data;
Node* next;
};
Node* createNode(int value) {
Node* newNode = new Node;
newNode->data = value;
newNode->next = nullptr;
return newNode;
}
工厂模式[编辑 | 编辑源代码]
class Shape {
public:
virtual void draw() = 0;
static Shape* create(int type);
};
Shape* Shape::create(int type) {
switch(type) {
case 1: return new Circle();
case 2: return new Square();
default: return nullptr;
}
}
最佳实践[编辑 | 编辑源代码]
- 总是检查分配是否成功(特别是大型分配)
- 每个new必须对应一个delete
- 数组使用delete[]释放
- 优先使用智能指针(如
std::unique_ptr
)管理动态内存 - 避免在频繁调用的代码路径中使用new/delete
常见问题[编辑 | 编辑源代码]
内存泄漏[编辑 | 编辑源代码]
忘记释放内存是最常见错误:
void leak() {
int* p = new int(10);
// 忘记delete p
} // 内存永久丢失
悬垂指针[编辑 | 编辑源代码]
int* p = new int(5);
delete p;
*p = 10; // 未定义行为!
性能考虑[编辑 | 编辑源代码]
new操作涉及系统调用,比栈分配慢得多。典型对比:
与malloc()的区别[编辑 | 编辑源代码]
特性 | new | malloc() |
---|---|---|
调用构造函数 | ✓ | ✗ |
返回类型 | 类型安全指针 | void* |
失败处理 | 异常或nothrow | 返回NULL |
大小计算 | 自动 | 需手动计算 |
扩展阅读[编辑 | 编辑源代码]
- C++17引入的带对齐分配的new:
align_val_t
- 重载类特定的new/delete运算符
- 内存池技术优化频繁分配