删除调用析构函数但不删除对象?

Gun*_*hin 1 c++ pointers destructor memory-management

所以我现在用c ++和指针工作了一年半,我想我让他们成功了.我之前多次调用对象上的删除,实际上删除了对象,或者至少我认为它们已经删除了.

下面的代码只是让我感到困惑:

#include <iostream>

class MyClass
{
public:
    int a;

    MyClass() : a(10) {
        std::cout << "constructor ran\n";
    }

    void method(std::string input_) {
        std::cout << param_ << "\n";
    }

    ~MyClass() {
        std::cout << "destructor ran\n";
    }

};

int main()
{

   MyClass* ptr = new MyClass;

   ptr->method("1");

   delete ptr;

   ptr->method("2.5");

}
Run Code Online (Sandbox Code Playgroud)

此代码输出:

constructor ran
1
destructor ran
2.5
Run Code Online (Sandbox Code Playgroud)

我很困惑为什么它没有抛出任何类型的错误 - 我期待一个异常或类似的内存,但没有.该for循环是有柜面有某种隐藏的垃圾收集,尽管据我所知,C中没有垃圾收集++.

任何人都可以解释为什么这个代码工作,或者我错误的代码,因为它不给我错误?

Bri*_*ell 13

你误解了什么delete.所有delete操作都是调用析构函数,并告诉分配器该内存是空闲的.它不会改变实际指针.除此之外的任何事情都是未定义的.

在这种情况下,它对指向的实际数据没有任何作用.该指针指向它之前指向的相同数据,并且在其上调用方法可以正常工作.但是,这种行为无法保证; 事实上,它明确没有具体说明.delete可以将数据清零; 或者分配器可以为其他东西分配相同的内存,或者编译器可以拒绝编译它.

为了提高性能,C++允许您做许多不安全的事情.这是其中之一.如果你想避免这种错误,最好这样做:

delete ptr;
ptr = NULL;
Run Code Online (Sandbox Code Playgroud)

确保您不会尝试重用指针,并且如果您确实没有使用未定义的行为,则会立即崩溃.

  • "*上面的调用方法工作得很好*"不准确,有一大堆的情况下它不会"工作得很好".正如其他人所提到的,重点是UB可以做*任何事情*包括出现在工作中. (2认同)

NPE*_*NPE 7

调用ptr->method("2.5")delete ptr未定义的行为.这意味着任何事情都可能发生,包括你正在观察的事情.


Lih*_*ihO 5

在这段代码中:

MyClass* ptr = new MyClass;
ptr->method("1");
delete ptr;
ptr->method("2.5");
Run Code Online (Sandbox Code Playgroud)

您正在访问已经释放的内存,这会产生未定义的行为,这意味着任何事情都可能发生,包括最坏的情况:它似乎正常工作.

这就是设置这样一个指针NULL而不是允许这种事情发生的好习惯的原因之一:

delete ptr;
ptr = NULL;
Run Code Online (Sandbox Code Playgroud)

虽然最好的办法是尽可能完全避免使用指针.