在C++里是怎么实现delete[]的

小编 349

在C++ 中,delete[] 用于释放一个由new[] 分配的数组。它会释放整个数组,而不仅仅是名列前茅个元素。delete[] 的实现与delete 的实现有所不同,因为数组的大小在运行时才能确定,因此需要一些额外的操作来跟踪数组的大小。

实现delete[] 的关键在于如何确定要释放多少内存。因为数组大小是在运行时确定的,所以需要存储数组大小。一种方法是在堆上分配一个额外的字节,用于存储数组大小。在分配内存时,分配的空间比请求的空间大一些,并将数组大小存储在开头的一个字节中。这样,delete[] 可以使用这个信息来释放正确数量的内存。

例如,以下代码使用new[] 在堆上分配一个包含10 个整数的数组,并将它们全部初始化为零:

int* array = new int[10](); // 注意括号,这将初始化数组元素为 0

此时,在内存中,数组的布局如下所示:

[array size] [element 0] [element 1] ... [element 9]

其中,[array size] 是存储数组大小的额外字节。在这种布局中,delete[] 的实现需要做两件事情:

  • 读取数组大小,以确定要释放多少内存。
  • 释放整个数组,包括额外的字节。

以下是一个简单的实现:

void operator delete[](void* ptr) noexcept {
    if (ptr != nullptr) {
        // 获取数组大小
        int* array_ptr = static_cast<int*>(ptr);
        const std::size_t array_size = array_ptr[-1];

        // 释放整个数组
        ::operator delete[](array_ptr, array_size + sizeof(std::size_t));
    }
}

这个实现使用了一个技巧,即通过将指针强制转换为int* 类型来读取数组大小。这是因为数组大小是存储在指针所指向的内存之前的额外字节中的,而指针指向的是名列前茅个元素。因此,将指针强制转换为int* 类型,然后减去1,就可以得到存储数组大小的额外字节的地址。

delete[] 的实现也需要注意一些异常情况。例如,如果指针为nullptr,则delete[] 不应该执行任何操作。此外,如果指针不是由new[] 分配的,也应该抛出异常。

总之,delete[] 的实现需要存储数组大小,并在释放内存时使用该信息来确定要释放多少内存。此外,实现还需要考虑异常情况,以确保代码的健壮性和正确性。

延伸阅读

C++ 中delete和delete[]是一样的吗

在C++ 中,delete 和delete[] 是不同的操作符,它们用于释放不同类型的内存。

delete 用于释放单个对象所占用的内存,而delete[] 用于释放数组所占用的内存。如果使用delete 释放数组所占用的内存,会导致未定义的行为,因为delete 只会释放单个对象所占用的内存,而不会释放整个数组所占用的内存。同样地,如果使用delete[] 释放单个对象所占用的内存,也会导致未定义的行为。

以下是使用delete 释放数组所占用的内存的错误示例:

int* array = new int[10];
delete array; // 错误!应该使用 delete[]

以下是使用delete[] 释放单个对象所占用的内存的错误示例:

int* value = new int;
delete[] value; // 错误!应该使用 delete

因此,在C++ 中,必须使用正确的操作符来释放相应类型的内存,否则会导致未定义的行为。为了避免这种问题,建议使用smart pointer 类型(如std::unique_ptr 和std::shared_ptr)来管理内存,这些类型会自动选择正确的操作符来释放内存。

回复

我来回复
  • 暂无回复内容

注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部