为什么不删除任何东西?

Kam*_*ave 21 c++ memory new-operator delete-operator

我正在玩内存动态分配,但我不明白.当用new语句分配一些内存时,我应该能够破坏指针指向使用的内存delete.

但是当我尝试时,这个delete命令似乎不起作用,因为指针指向的空间似乎没有被清空.

让我们以这个真正基本的代码为例:

#include <iostream>  

using namespace std;

int main()  
{  
    //I create a pointer-to-integer pTest, make it point to some new space,  
    // and fulfill this free space with a number;  
    int* pTest;  
    pTest = new int;  
    *(pTest) = 3;  
    cout << *(pTest) << endl; 

    // things are working well so far. Let's destroy this
    // dynamically allocated space!
    delete pTest;

    //OK, now I guess the data pTest pointed to has been destroyed 
    cout << *(pTest) << endl; // Oh... Well, I was mistaking.  

    return 0;  
}  
Run Code Online (Sandbox Code Playgroud)

任何线索?

GMa*_*ckG 55

是时候了解未定义的行为是什么.:)

在C++中,当你做一些非法/荒谬/坏/等的事情.标准经常说"它会导致不明确的行为".这意味着从那时起,程序的状态完全无法保证,任何事情都可能发生.

在你做最后一次的时候*(pTest),你会得到未定义的行为.这是因为pTest没有指向有效对象,并且取消引用这样的指针是未定义的.所以你所看到的是完全允许的:未定义的输出.

你所做的就是说"我完成了这个分配." 一旦你说过,你就不应该(实际上,不能)再检查或关心那个记忆.从某种程度上说,释放某些东西然后尝试使用它甚至没有概念意义; 你说你做完了!

你的输出在某种程度上是可预测的:可能,你的操作系统只是说"好吧,谢谢你的记忆"就是这样.它没有理由实际"重置"内存,或做任何特别的事情.当没有人(包括你自己的程序)没有使用它时,这确实是浪费时间.

但请记住,此输出完全未定义.不要尝试使用不存在的对象.也许更好的测试是:

#include <iostream>

struct foo
{
    ~foo()
    {
        std::cout << "foo is gone :(" << std::endl;
    }
};

int main(void)
{
    foo* f = new foo();
    delete f; // you'll see that the object is destroyed.
}
Run Code Online (Sandbox Code Playgroud)

虽然看起来你正在寻找内存本身会发生什么.请记住,摆脱内存然后尝试使用它是没有意义的,所以答案是:谁知道.这取决于您的特定平台,C++并不关心.

  • 关于未定义行为的丑陋之处在于它大部分时间看起来都很好. (28认同)

Mac*_*ade 10

调用delete会将内存区域标记为空闲.它不需要重置其旧值.

在调用delete之后,建议将指针设置为0:

delete pTest;
pTest = 0;
Run Code Online (Sandbox Code Playgroud)

  • 更好的解决方案是确保变量在删除后很快超出范围,因此无法重复使用. (9认同)
  • 我建议在调用`delete`之后不要使用变量_at all_(...除非,当然,它被重新分配给其他东西). (2认同)

Căt*_*tiș 5

delete运算符调用对象的析构函数并释放先前分配给该对象的内存.它不会影响指向已删除对象的指针变量.

因此,当取消引用指向被破坏对象的指针时,您将遇到麻烦.


Max*_*xVT 5

答案是表现.

这是一个伟大的调试援助,以填补无效值(所有释放的内存0xCCCCCCCC,0xDEADDEAD等等)来捕捉试图使用过时的指针已经释放的内存.

但是修改释放的内存会花费CPU时间,因此出于性能原因,操作系统只会将释放的内存块添加到其"空闲"列表中,并保持内容不变.