删除运算符的确切操作

the exact operation of the delete operator

我听说过很多关于 C++ delete operator 并且到目前为止我也经常使用它,但我不知道它的真正作用到底是什么。
我在网上看到的是 "Deallocating storage space" 上关于它的讨论,但对我来说完全理解这个问题并没有什么意义。

请查看下面的代码片段。

int main()
{
   int* p = new int(6);
   cout << *p << endl;
   delete p;
}

指针 p 有自己的地址,因为它是一个变量 (#1)。指针 p 本身也有一个地址,因为它是一个指针(#2)。该对象(未命名)在其内存块中包含值 6,并且该内存块的地址与 #2 的地址相同。 (因为指针使用该地址指向该对象。)

现在,执行delete;后地址#1和#2会发生什么?
C++ 语言对此有何看法?
各种编译器对这种情况的影响是什么?

关于

The exact operation of the delete operator

问题中的示例代码:

delete p;

那是一个delete表达式,不是直接调用delete运算符。运算符是一个释放函数,通常由 delete 表达式调用,在 delete 表达式调用对象析构函数(或对于数组,这样的序列)之后。事情是这样的:

  1. 如果 p 指向一个 class 类型的对象,那么调用它的析构函数来清理东西,例如释放资源。

  2. 调用相关的释放函数 operator delete 来释放内存。这通常是全局 operator delete,但它可以是由相关 class 定义的 operator delete

值得注意的是,对于放置 new 表达式,如果在 new 表达式求值期间构造失败,则使用相同的分配器参数调用放置释放函数,但稍后 delete 表达式只调用普通的标准参数 operator delete。我不知道这样做的理由。但这导致了一些错误,尤其是 MFC 中一个臭名昭著的错误,它仅出现在调试版本中,内存泄漏。

int main() {
    int* p;             // p is at address #1 and the value uninitialized. p will
                        // be at address #1 throughout the whole program.
                        // It is only the value of p that can change.

    p = new int(6);     // The value of p is set to address #2 and your
                        // program now has ownership of sizeof(int) bytes
                        // starting from address #2. The int at address #2
                        // is initialized with the value 6.
    cout << *p << endl;

    delete p;           // Your program releases ownership of the memory at
                        // address #2 and you are not allowed to use it anymore.
                        // The value of p is undefined.

    return 0;
}

delete p 之后,p 仍然具有与以前相同的地址。对象不见了,所以它没有地址。它曾经占用的字节可能被用于其他用途,或者可能已返回给 OS;如果不调用未定义的行为,您将无法查看它们。

p 的值不再有用 - 您不能对 p 做太多事情,只能为其分配一个新值或让它被销毁。

这就是语言所说的,编译器会实现它。

这里有更多详细信息:http://en.cppreference.com/w/cpp/language/delete

Now, what will happen over the address #1, #2 after executing delete; (in the code) please?

指针 p 将有一个未定义的值,但它会保留其地址(“#1”)。

位于 *pint 对象(地址为“#2”)不再存在。该地址现在描述了可在未来分配中免费使用的内存。


What does the C++ language say about this?

这个:

[C++14: 5.3.5/1]: The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression. [..]

[C++14: 5.3.5/7]: If the value of the operand of the delete-expression is not a null pointer value, then:

  • If the allocation call for the new-expression for the object to be deleted was not omitted (5.3.4), the delete-expression shall call a deallocation function (3.7.4.2). The value returned from the allocation call of the new-expression shall be passed as the first argument to the deallocation function.
  • Otherwise, the delete-expression will not call a deallocation function (3.7.4.2).

And what can be the effect of various compilers on the case?

只要他们合规,none。所有编译器的行为方式必须相同。