跳到主要内容
版本:1.0

new

new 是 C++98/03 中最核心的动态内存分配工具之一。它不仅负责在自由存储区(通常称为堆)申请内存,还会自动调用对象构造函数完成初始化。

和 C 语言的 malloc 相比,new 的最大特点是“类型安全 + 构造语义”:

  1. 你不需要手动计算字节数。
  2. 返回值是正确类型指针,不需要强制转换。
  3. 对类类型会自动执行构造函数。
  4. 分配失败默认抛出异常,而不是返回空指针。

基本语法

最常见形式:

T* p = new T;
T* p2 = new T(args...);
T* arr = new T[n];

解释:

  • new T:分配一个 T 对象,并执行默认构造。
  • new T(args...):分配一个 T 对象,并执行对应构造函数。
  • new T[n]:分配 nT 对象的数组,并逐个构造。

分配内置类型

#include <iostream>

int main() {
int* p = new int(42);
std::cout << *p << '\n';

delete p;
p = 0;
return 0;
}

new int(42) 表示申请一个 int 并初始化为 42

分配类对象

#include <iostream>
#include <string>

class Person {
public:
Person(const std::string& n, int a) : name(n), age(a) {
std::cout << "Person ctor\n";
}

~Person() {
std::cout << "Person dtor\n";
}

void print() const {
std::cout << name << " (" << age << ")\n";
}

private:
std::string name;
int age;
};

int main() {
Person* p = new Person("Alice", 20);
p->print();

delete p;
p = 0;
return 0;
}

只要使用 new 创建对象,对应释放时就应使用 delete,这样析构函数才能正确执行。

数组分配

#include <iostream>

int main() {
int n = 5;
int* arr = new int[n];

for (int i = 0; i < n; ++i) {
arr[i] = i * 10;
}

for (int i = 0; i < n; ++i) {
std::cout << arr[i] << ' ';
}
std::cout << '\n';

delete[] arr;
arr = 0;
return 0;
}

数组由 new[] 创建,必须由 delete[] 释放,二者必须匹配。

失败处理与异常

默认情况下,分配失败会抛出 std::bad_alloc

#include <iostream>
#include <new>

int main() {
try {
int* p = new int[1000000000];
delete[] p;
} catch (const std::bad_alloc&) {
std::cout << "memory allocation failed\n";
}

return 0;
}

如果你不希望抛异常,可使用 std::nothrow

#include <iostream>
#include <new>

int main() {
int* p = new (std::nothrow) int[1000000000];
if (!p) {
std::cout << "allocation failed, p is null\n";
return 0;
}

delete[] p;
return 0;
}

new 与 malloc 的区别

对比项newmalloc
所属C++ 运算符C 标准库函数
返回类型目标类型指针void*
失败行为std::bad_alloc(默认)返回 NULL
初始化可调用构造函数只分配原始字节
释放方式delete / delete[]free

最重要原则:

  1. new 必须配对 delete
  2. new[] 必须配对 delete[]
  3. 不要交叉使用 new/freemalloc/delete

常见错误

  1. 忘记释放,导致内存泄漏。
  2. 使用错误释放方式(new[]delete)。
  3. 重复释放同一指针(double delete)。
  4. 释放后继续解引用悬空指针。

示意:

int* p = new int(10);
delete p;
// *p = 20; // 错误:悬空指针
p = 0;

小结

new 在 C++98/03 中承担了“申请内存 + 构造对象”的双重职责,是面向对象内存管理的核心入口。掌握 new 时,关键不是“怎么申请”,而是“怎么成对释放并保持生命周期清晰”。