1

所以我已经使用 c++ 和指针工作了一年半了,我认为我让它们成功了。我之前已经多次对对象调用 delete 并且对象实际上被删除了,或者至少我认为它们确实被删除了。

下面的代码让我很困惑:

#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");

}

此代码输出:

constructor ran
1
destructor ran
2.5

我很困惑为什么它没有抛出任何类型的错误 - 我期待内存超出范围异常或类似情况,但什么也没有。循环在那里,for以防有某种隐藏的垃圾收集,即使据我所知,C++ 中没有垃圾收集。

谁能解释为什么这段代码有效,或者我在哪里出错了,因为它不会给我错误?

4

4 回答 4

15

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

在这种情况下,它对指向的实际数据没有任何作用。该指针指向它之前指向的相同数据,并且在其上调用方法就可以了。但是,不能保证这种行为;事实上,它是明确未指定的。delete可以将数据归零;或者分配器可以为其他东西分配相同的内存,或者编译器可以拒绝编译它。

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

delete ptr;
ptr = NULL;

以确保您不会尝试重用指针,并且如果这样做会立即崩溃,而不是具有未定义的行为。

于 2013-09-24T19:40:51.203 回答
7

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

于 2013-09-24T19:40:40.137 回答
5

在这段代码中:

MyClass* ptr = new MyClass;
ptr->method("1");
delete ptr;
ptr->method("2.5");

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

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

delete ptr;
ptr = NULL;

尽管最好的办法是尽可能完全避免使用指针。

于 2013-09-24T19:41:13.517 回答
0

您正在访问内存,该内存在被另一个新调用使用之前不会重置。但是,每次调用 delete 时,将指针设置为NULL.

于 2013-09-24T19:51:24.357 回答