C++:删除这个; return x;

C++: delete this; return x;

嘿,我对某些 C++ 行为很好奇,因为如果此行为是一致的,那么我正在处理的代码在简单性方面将从中受益匪浅。基本上,我的想法是让我的对象 A 中的特定函数计算返回 float 的复杂计算,但就在返回 float 之前,偶尔会调用 delete this.


1

这是我要验证的功能是否一致的代码示例。

#include <iostream>
#include <stdio.h>
#include <cstdlib>

using namespace std;

struct A
{
    float test(float a) {delete this; return a;}
};

int main()
{
    A *a = new A();
    cout << a->test(1.f) << endl;
    cout << "deleted?" << endl;
    cout << a->test(1.f) << endl;
}

输出变为:

1.0
deleted?
*** Error in `./test': double free or corruption (fasttop): 0x0105d008 *** Aborted (core dumped)

我认为这意味着对象已被正确删除(内存中还剩下什么?A 的不可调用骨架?类型化指针?空指针?),但我不确定我的看法是否正确。如果是这样,这种行为是否会保持一致(我的函数将只返回本机类型(浮点数))


2

此外,我很好奇为什么这似乎不起作用:

struct A
{
    float test(float a) {delete this; return a;}
};

int main()
{
    A a;
    cout << a.test(1.f) << endl;
}

此编译但在返回任何内容之前抛出以下错误。

*** Error in `./test': free(): invalid pointer: 0xbe9e4c64 *** Aborted (core dumped)

注意请不要用一长串的解释来说明为什么这是不好的coding/etiquette或其他什么,不在乎,我只是对可能性感兴趣。

成员函数调用 delete this; 是安全的 如果 您知道该对象是使用标量 new 分配的,并且其他任何东西都不会使用之后的对象。

在您的第一个示例中,在第一次调用 a->test(1.f) 后,a 变为 "dangling pointer"。当您取消引用它以第二次调用 test 时,您调用了未定义的行为。

在您的第二个示例中,delete this; 语句是未定义行为,因为对象不是使用 new 创建的。

行为未定义,但在典型的现代实现中,访问释放内存的实用 "possibilities" 包括(但不限于):

  1. delete 在 运行 时间库级别 (RTL) 释放内存,但不会 return 到 OS。 IE。 OS 级内存保护未启用,OS 继续看到已分配的内存。但是,存储在已释放内存块中的内部 RTL 数据会破坏您的数据。结果:通过指针访问不会导致您的代码崩溃,但数据看起来毫无意义(被破坏)

  2. 与 1 相同,但内部 RTL 数据恰好不会与您的关键数据重叠。代码不会崩溃并继续工作 "as if" 一切都是 "fine"。

  3. delete 释放内存给 OS。 OS 级内存保护已启用。任何通过指针访问的尝试都会导致立即崩溃。

您的示例按照第二种情况进行,即存储在对象中的数据似乎在您释放内存后仍保持不变。

您在代码中观察到的崩溃发生是因为 RTL 检测到两次 free 尝试(或尝试 free 非动态内存,如第二个示例),这有点除了您问题的上下文中的要点。