重载new和delete

通过重载来改变new和delete的方法。可以改变内存的来源。默认的operator new底层实现是malloc。

void* operator new(size_t sz){
return malloc(sz);
}
void operator delete(void* p){
free(p);
}

new和delete

new会先申请空间,系统随后会在新申请的空间上调用构造函数。delete会先在空间上调用析构函数,再释放空间。

A* a=new A();
delete a;

new[]和delete[]

new[]会先申请足够大的空间再分别调用每个元素的构造函数。delete[]会先从后往前的调用析构函数再释放整个空间。

A* arr=new A[20];
delete []arr;

注意:

  • new 和delete 必须相互兼容。new 对应于delete, new[] 对应于delete[]。
  • 如果有多个构造函数,则必须以相同的方式使用new ,要么都带中括号,要么都不带,因为只有一个析构函数,所有的构造函数都必须与它兼容。然而,可以在一个构造函数中使用new 初始化指针,而在另一个构造函数中将指针初始化为空(0或C++11 中的nullptr),这是因为delete (无论是带中括号还是不带中括号)可以用于空指针。
  • NULL、0还是nullptr:以前,空指针可以用0或NULL (在很多头文件中, NULL是一个被定义为0的符号常量)来表示。C程序员通常使用NULL而不是0,以指出这是一个指针,就像使用‘\0’而不是0来表示空字符,以指出这是一个字符一样。然而,C++传统上更喜欢用简单的0,而不是等价的NULL。但正如前面指出的,C++11提供了关键字nullptr,这是一种更好的选择。

bad_alloc 异常

对于使用new 导致的内存分配问题,C++的最新处理方式是让new 引发bad_alloc 异常。头文件new 包含bad_alloc 类的声明,它是从exception类公有的派生而来的。但在以前,当无法分配请求的内存量时,new 返回一个空指针。

bad_alloc 是 C++ 中的一个异常类,它定义在 <new> 头文件中。当动态内存分配请求(如 new 运算符)失败时,可能会抛出 bad_alloc 异常。通常,这种异常表明系统无法提供请求的内存量,常见的原因可能是内存不足或者请求分配的内存大小超出了系统可用的最大内存限制。

下面是 bad_alloc 异常的一个使用示例:

#include <iostream>
#include <new> // 必须包含这个头文件来使用 bad_alloc

int main() {
    try {
        // 尝试分配非常大的内存空间,可能会失败并抛出 bad_alloc 异常
        int* myHugeArray = new int[1000000000000];
        // 使用分配的内存...
        delete[] myHugeArray; // 释放内存
    }
    catch (const std::bad_alloc& e) {
        // 处理内存分配失败的情况
        std::cerr << "内存分配失败: " << e.what() << '\n';
    }
    return 0;
}

如果内存分配成功,则代码会继续执行并最终释放内存。如果内存分配失败,则 new 表达式将抛出一个 bad_alloc 类型的异常,紧接着程序将进入 catch 代码块,输出错误信息,并且干净地退出,这能够防止内存泄漏和其他潜在的问题。

可以通过异常处理机制来增强程序的鲁棒性,当面对资源限制或者请求超出理智大小时,程序可以通过 bad_alloc 异常来优雅地处理这类故障。