<new> 是 C++ 标准库中的一个头文件,提供了内存分配和管理的功能,主要包括动态内存分配、对象创建和异常处理机制。它是 C++ 中内存管理的重要部分,支持低级别的内存分配,同时也提供了内存分配失败时的异常处理机制。


目录

  1. 简介
  2. 动态内存分配
  3. new 和 delete 的异常处理
  4. 内存分配失败的处理
  5. placement new
  6. 结论

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++ 提供了内存管理的基本工具,允许开发者进行动态内存分配和对象构造,同时支持异常处理和自定义内存分配。newdelete 操作符是 C++ 中最常见的内存管理工具,而 placement new 使得开发者可以在自定义内存区域上构造对象。

内存分配失败时,C++ 提供了异常处理机制,开发者可以通过捕获 std::bad_alloc 异常或使用 std::nothrow 进行错误处理。通过合理使用 newdelete,开发者可以有效管理内存,避免内存泄漏和未定义行为。

推荐阅读: