delete[]和delete的行为似乎相似

delete[] and delete seems to behave alike

本文关键字:delete 相似      更新时间:2023-10-16

这里,如果我使用deletedelete[],输出仍然是70。我能知道为什么吗?

#include<iostream>
using namespace std;
int main()
{
    int* c = new int[100];
    for(int i=0; i<98; i++)
    {
        c[i] = i;
    }
    cout<<c[70]<<endl;
    delete[] c;
      or
    delete c;
    cout<<c[70]<<endl; //outputs 70 even after delete[] or delete
    return 0;
}

访问已删除的内存是未定义的行为。用错误的delete删除也是UB。任何进一步的讨论都是毫无意义的,因为你无法可靠地期待任何结果。

在许多情况下,UB只会做"正确"的事情,但你需要意识到,这完全是"偶然"的,可能会随着另一个编译器、同一编译器的另一个版本、天气。。。为了获得正确的代码,您需要避免UB的所有情况,即使是那些看起来有效的情况。

使用new只会为程序分配一些内存,并返回一个指向所述内存地址的指针,为数据类型保留所需的内存。当您稍后使用delete时,它会"释放"内存,但不会删除其内容。如果您有一个值为70的int存储在该地址,那么它仍将包含70,直到另一个应用程序需要一些内存,获得所述地址并在其中放入另一个值。

如果您使用new为数组分配内存,您将保留以下内存块,直到有足够的块用于指定的数组长度。

假设您执行以下操作:

int main() {
    int* array = new int[10]; // array now points to the first block of the allocated memory
    delete array;             // since array points to the first block of the array, it will only free that block, but nothing else, causing a memory leak
    delete[] array;           // will free all memory allocated by the previous new
    // Note that you should never free allocated memory twice, like in this code sample. Using delete on already freed memory is undefined behaviour!
]

始终对单个变量使用delete,对数组使用delete[]

演示您的问题:

int main() {
    int* c = new int[10];  // We allocate memory for an array of 10 ints
    c[0] = 1;              // We set the value of the first int inside the array to 1
    delete[] c;
    /* 
     * We free the previously allocated memory.
     * Note that this does not delete the CONTENT of the memory!
     * c does still point towards the first block of the array!
     */
    std::cout << c[0];
    /* 
     * Firstly, this is undefined behaviour (Accessing deallocated memory).
     * However, this will output 1,
     * unless some other process allocated the memory at the address
     * and filled it with another value already. (Very unlikely)
     */
    return 0;
}

如果要删除/覆盖已删除内存的内容,可以使用std::memset

示例:

#include <cstring>
int main() {
    std::size_t length = 10;
    int* c = new int[length];
    c[0] = 1;
    std::cout << c[0] << std::endl; // Will output 1
    std::memset( c, 0, length );    // Fill the memory with 0 bytes
    delete[] c;                     // Now we free the array's memory
    std::cout << c[0] << std::endl; // Will output 0
}

正如其他人所指出的,它的未定义行为和任何事情都可能发生。借助像valgrind这样的工具可以很容易地捕捉到这些。