<new>
是 C++ 标准库中的一个头文件,提供了内存分配和管理的功能,主要包括动态内存分配、对象创建和异常处理机制。它是 C++ 中内存管理的重要部分,支持低级别的内存分配,同时也提供了内存分配失败时的异常处理机制。
目录
1. 简介
<new>
头文件定义了用于动态内存管理的操作符和函数。它提供了内存分配和对象构造的能力,并处理内存分配失败时的异常。new
操作符和 delete
操作符允许在堆上动态分配内存,并对动态分配的对象进行构造和析构。
要使用 <new>
,只需包含:
#include <new>
2. 动态内存分配
2.1 new 操作符
new
操作符用于在堆上动态分配内存,并调用对象的构造函数来初始化该内存区域。它返回一个指向分配内存的指针。
语法:
pointer = new type;
pointer = new type(initializer);
type
:要分配的对象类型。initializer
:可选的初始化参数,用于初始化分配的内存中的对象。
示例:
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor called\n";
}
void display() {
std::cout << "MyClass object\n";
}
};
int main() {
MyClass* ptr = new MyClass(); // 动态分配内存并构造对象
ptr->display();
delete ptr; // 手动释放内存
return 0;
}
在此示例中,new MyClass()
在堆上分配内存并调用构造函数创建 MyClass
对象。当 delete ptr
被调用时,内存被释放,且对象的析构函数被调用。
2.2 delete 操作符
delete
操作符用于释放 new
操作符分配的内存,并调用对象的析构函数来销毁对象。
语法:
delete pointer;
delete[] pointer; // 删除数组
pointer
:指向要删除的对象或对象数组的指针。delete[]
用于释放通过new[]
分配的对象数组。
示例:
#include <iostream>
int main() {
int* p = new int(10); // 动态分配一个整数
std::cout << *p << std::endl;
delete p; // 释放单个对象的内存
int* arr = new int[5]; // 动态分配一个整数数组
delete[] arr; // 释放数组的内存
return 0;
}
3. new 和 delete 的异常处理
在 C++ 中,如果 new
无法分配足够的内存,默认情况下,它会抛出 std::bad_alloc
异常。但是,可以通过 new(std::nothrow)
来禁止异常抛出,并返回一个空指针。
默认情况下的异常处理
#include <iostream>
#include <new>
int main() {
try {
int* ptr = new int[10000000000]; // 尝试分配大量内存
} catch (const std::bad_alloc& e) {
std::cout << "Memory allocation failed: " << e.what() << std::endl;
}
return 0;
}
使用 std::nothrow
防止异常
#include <iostream>
#include <new>
int main() {
int* ptr = new(std::nothrow) int[10000000000]; // 防止异常抛出
if (ptr == nullptr) {
std::cout << "Memory allocation failed" << std::endl;
} else {
delete[] ptr;
}
return 0;
}
4. 内存分配失败的处理
内存分配失败的情况通常会通过抛出异常来处理。在默认情况下,new
操作符会抛出 std::bad_alloc
异常。开发者可以捕获此异常并采取适当的措施。
当 std::nothrow
被传递给 new
操作符时,new
将返回一个空指针(nullptr
)而不是抛出异常,允许程序控制如何处理内存分配失败的情况。
5. Placement new
placement new
是 C++ 中的一种特殊形式的 new
操作符,允许在指定的内存位置上构造对象。它与普通的 new
操作符不同,因为它不分配内存,只是调用构造函数在给定的内存区域中创建对象。
语法:
void* memory = operator new(size_t size); // 分配原始内存
new (memory) Type; // 在分配的内存上构造对象
示例:
#include <iostream>
#include <new>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor called\n";
}
void display() {
std::cout << "MyClass object\n";
}
};
int main() {
char buffer[sizeof(MyClass)]; // 预先分配内存
MyClass* ptr = new (buffer) MyClass(); // 在预分配内存上构造对象
ptr->display();
ptr->~MyClass(); // 显式调用析构函数
return 0;
}
在此示例中,placement new
在预分配的内存 buffer
上构造 MyClass
对象。注意,placement new
并不会分配内存,它只是利用已有的内存空间。
6. 结论
<new>
头文件为 C++ 提供了内存管理的基本工具,允许开发者进行动态内存分配和对象构造,同时支持异常处理和自定义内存分配。new
和 delete
操作符是 C++ 中最常见的内存管理工具,而 placement new
使得开发者可以在自定义内存区域上构造对象。
内存分配失败时,C++ 提供了异常处理机制,开发者可以通过捕获 std::bad_alloc
异常或使用 std::nothrow
进行错误处理。通过合理使用 new
和 delete
,开发者可以有效管理内存,避免内存泄漏和未定义行为。
推荐阅读:
发表回复