访问不正确创建的变量导致无限循环

Jim*_*ilo 2 c++ infinite-loop inner-classes

为什么这会进入无限循环以及为什么它会转储 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;
}

Run Code Online (Sandbox Code Playgroud)

我在玩内部类时发现了这个。C++ 不是主要语言,而且我已经中断了很长一段时间才接触到这一点,所以我想通过这个来提高我的知识。我确实知道在正确创建 Outer 之前我不应该使用它的字段,所以这通常是一件非常糟糕的事情。我觉得真正的答案可能只是因为我没有编译器错误并不意味着某些事情是正确的。

一个有趣的旁注是,如果我删除任何一个多余的字符串,我会收到编译器错误,或者它只会出现段错误,而这正是我所期望的。我从我正在使用的一个更复杂的结构中总结出这一点,所涉及的元素似乎是引起这种反应所需的最低限度。

Yks*_*nen 7

我确实知道在正确创建 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;
};
Run Code Online (Sandbox Code Playgroud)