我观察到删除语义的一些意外行为。例如,使用以下C ++代码:
class Base{
public:
Base(int tmp) : x(tmp) {}
~Base() { std::cout << "Inside Base::~Base()" << std::endl; }
void foo() { std::cout << "Inside Base::foo()" << std::endl; }
int x;
};
...
int main(int argc, char** argv)
{
Base* b = new Base(10);
delete b;
b->foo();
std::cout << "b->x: " << b->x << std::endl;
}
我从Visual Studio 2008收到以下输出:
Inside Base::~Base()
Inside Base::foo()
b->x: 2359492
为什么在致电delete b
后,我仍然可以调用Base::foo()
方法?
谢谢, 克里斯
答案 0 :(得分:2)
正如其他人已经在评论中指出的那样,这是未定义的行为。这意味着实现可以做任何想做的事情,包括返回您期望的值。
它还可能决定格式化你的硬盘或使着名的恶魔飞出你的鼻子。
有关如果您调用UB可能会发生什么的一些轶事,请参阅this question
答案 1 :(得分:2)
为什么在致电
delete b
后,我仍然可以调用Base::foo()
方法?
因为,与所有未定义的行为一样,程序不需要优雅地失败。
在这种情况下,无法保证已删除的内存无法访问;即使这样,调用非虚拟成员函数也不太可能访问该内存。因此,除非程序在调用成员函数之前专门检查对象是否有效(这将是非常昂贵的,因此默认情况下没有实现会这样做),所以有可能按预期调用函数并隐藏错误。
答案 2 :(得分:1)
删除某些内容后,heap
会将其回收。这意味着如果您在删除之后没有立即访问它,则无法保证您的旧信息将存在。人们之所以说不去访问它是因为你无法控制它可能是什么。这种类型的乱码输出是预期的&#34;删除变量后的未定义行为。
正如@LuchianGrigore所说,&#34;不要这样做&#34; !!!!!