为什么这个C++方法执行最后一个定义的对象的主体,而不是由于指向死对象而失败?



考虑以下C++代码:

#include <iostream>
using namespace std;
class Hello {
public:
Hello(const char* name) : name(name)
{}
void body() {
cout << name;
cout << " bodyn";
}
const char* name;
};

Hello* first;
void create() {
Hello wellington("Wellington");
first = &wellington;
}
int main() {
create();
Hello rob("Rob");
Hello james("James");
Hello donald("Donald");    
//    cout << "First points to: " << first << "n";
//    cout << "Rob is at: " << &rob << "n";
//    cout << "Donald is at: " << &donald << "n";
first->body();
}

很明显,在函数create中,我们创建了一个Hello对象"Wellington",它是我们保存在first中的指针,在这个过程结束后最终被销毁。之后,又创建了几个Hello对象,"Donald"是最后一个对象。

令人惊讶的是:尽管"first"指向一个"dead"对象,但body方法被正确执行。。就好像第一个指的是唐纳德。然而,指针不同,在first指向的点和Rob所在的点之后的Donald指针。另一件奇怪的事情是,当包含注释行(打印指针(时,名称再次无法正确打印。最后,正如预期的那样,使用first->name检查指向对象的名称只返回了胡言乱语。

那么,这里发生了什么?尽管指向的对象已不存在,但为什么使用Donald的名称正确执行body方法?

所写的是一个代码,它产生了一个所谓的未定义行为(UB(,部分是取消引用指向生命周期结束的对象的指针。

碰巧"first"捕获的死对象地址与现有对象的地址匹配。

当代码是UB时,任何事情都是可能的,这就是为什么不能编写它。

令人惊讶的是:尽管"first"指向一个"dead"对象,但body方法被正确执行。。

为什么这让你感到惊讶?通过无效指针进行访问具有未定义的行为。当行为未定义时,不能保证它不是"正确执行"(无论你期望的是什么"正确"(。

另一件奇怪的事情是,当包含注释行(打印指针(时,名称再次无法正确打印。

为什么这对你来说很奇怪?当行为未定义时,不能保证"再次正确打印"(无论您期望的是什么"正确"(。

当程序未定义时,程序的行为不会得到任何保证。

那么,这里发生了什么?尽管指向的对象已不存在,但为什么使用Donald的名称正确执行body方法?

程序的行为未定义。

相关内容

最新更新