[英]Infinite loop from access of improperly created variables
为什么这个 go 会进入无限循环,为什么会转储 char 0x20?
#include <iostream>
struct Outer {
Outer(std::string &outerString,
std::string &superfluousString1,
std::string &superfluousString2) :
outerString(outerString),
inner(*this) {}
struct Inner {
Inner(Outer &outer) {
std::cout << outer.outerString;
}
} inner;
std::string &outerString;
};
int main() {
std::string
outerString("outerString"),
superfluousString1("superfluousString1"),
superfluousString2("superfluousString2");
Outer outer(outerString, superfluousString1, superfluousString2);
return 0;
}
我发现了这个我正在玩内部类的惠斯特。 C++ 不是主要语言,我是从长期的中断中来的,所以我问这个是为了提高我的知识。 我知道在正确创建 Outer 之前我不应该使用它,所以这通常是一件非常糟糕的事情。 我觉得真正的答案很可能只是因为我没有编译器错误并不意味着某些事情是正确的。
一个有趣的旁注是,如果我删除任何一个多余的字符串,我会得到一个编译器错误,或者它只会出现段错误,而这正是我所期望的。 我从我正在玩的一个更复杂的结构中提炼出来,所涉及的元素似乎是引起这种反应所需的最低限度。
我知道在正确创建之前我不应该使用 Outer 的字段
不必要。 您不能在初始化之前使用成员,但可以使用已经初始化的成员来初始化其他成员。 问题是成员是按照声明的顺序初始化的,而不是按照它们出现在初始化列表中的顺序。 inner
在outerString
之前声明,因此它总是先初始化。
我觉得真正的答案很可能只是因为我没有编译器错误并不意味着某些事情是正确的。
这是正确的,你有未定义的行为,因为你在初始化之前访问了一个引用( outerString
)。 如果您启用了警告,您的编译器应该警告您(请在线查看警告)。
一个有趣的旁注是,如果我删除任何一个多余的字符串,我会得到一个编译器错误,或者它只会出现段错误,而这正是我所期望的。
未定义行为是未定义的,任何事情都可能发生。 对我来说,来自一个编译器的程序不打印任何内容并正常退出,来自不同编译器的程序打印大量空格然后崩溃。
您可以通过重新排序您的成员来使其工作(在线查看):
struct Outer {
Outer(std::string &outerString, std::string &superfluousString, std::string &innerString): outerString(outerString), inner(*this) {}
std::string &outerString; //declared before 'inner'
struct Inner {
Inner(Outer &outer) {
std::cout << outer.outerString;
}
} inner;
};
Class成员在class定义内按声明顺序初始化; 不是按照 ctor-initializer 列表中初始化程序的顺序。
现代编译器可以警告这种差异,如果默认情况下没有发生,您可能需要启用更多警告。
因此,您的程序在绑定之前确实使用了引用Outer::outerString
,从而导致未定义的行为。
如果在Outer
的 class 定义outerString
的声明移动到inner
之前,代码应该定义明确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.