所以我现在用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");
}
此代码输出:
constructor ran
1
destructor ran
2.5
我很困惑为什么它没有抛出任何类型的错误 - 我期待一个内存超出范围异常或类似,但没有。 for
循环就在那里,因为有一些隐藏的垃圾收集,尽管据我所知在c ++中没有垃圾收集。
任何人都可以解释一下为什么这段代码有效,或者我的代码出错了,因为它没有给我错误?
答案 0 :(得分:13)
你误解了delete
的作用。所有delete
都会调用析构函数,并告诉分配器该内存是空闲的。它不会改变实际指针。除此之外的任何事情都是未定义的。
在这种情况下,它对指向的实际数据没有任何作用。该指针指向它之前指向的相同数据,并且在其上调用方法可以正常工作。但是,这种行为无法保证;事实上,它明确没有具体说明。 delete
可以将数据清零;或者分配器可以为其他东西分配相同的内存,或者编译器可以拒绝编译它。
为了提高性能,C ++允许你做许多不安全的事情。这是其中之一。如果你想避免这种错误,最好这样做:
delete ptr;
ptr = NULL;
确保您不会尝试重用指针,并且如果您没有使用未定义的行为,则会立即崩溃。
答案 1 :(得分:7)
在ptr->method("2.5")
undefined behaviour之后致电delete ptr
。这意味着任何都可能发生,包括您正在观察的内容。
答案 2 :(得分:5)
在此代码中:
MyClass* ptr = new MyClass;
ptr->method("1");
delete ptr;
ptr->method("2.5");
您正在访问已被释放的内存,这会产生 未定义的行为 ,这意味着任何事情都可能发生,包括最糟糕的情况:它似乎正常工作
这就是为什么将这样的指针设置为NULL
而不是允许发生这种事情的好习惯之一的原因之一:
delete ptr;
ptr = NULL;
尽管最好的办法是尽可能完全避免使用指针。
答案 3 :(得分:0)
您正在访问内存,在其他新呼叫使用之前不会重置。但是每次调用delete时都是一个好习惯,就是将指针设置为NULL
。 / p>