如果没有endl,则重载的ostream操作符分段错误

shi*_*ilk 6 c++ vector operator-overloading ostream

class foo {
    public:
    friend ostream& operator << (ostream &os, const foo &f);
    foo(int n) : a(n) {}
    private:
    vector <int> a;
};

ostream& operator << (ostream &os, const foo &f) {
    for (int i = 0; i < f.a.size(); ++i)
        os << f.a[i] << " ";
    os << endl; // why is this line a must?
}

int main(void) {
    foo f(2);
    cout << f << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,如果标记的行被删除,会出现段错误,有人可以解释一下原因吗?

小智 17

ostream& operator << (ostream &os, const foo &f) {
    for (int i = 0; i < f.a.size(); ++i)
        os << f.a[i] << " ";
    os << endl; // why is this line a must?
}
Run Code Online (Sandbox Code Playgroud)

不是躁狂的.由于您没有返回,因此导致了段错误os

ostream& operator << (ostream &os, const foo &f) {
    for (int i = 0; i < f.a.size(); ++i)
        os << f.a[i] << " ";
    return os; // Here
}
Run Code Online (Sandbox Code Playgroud)

如果你不返回ostream,它是未定义的行为.这endl是在冲你的os.这就是它似乎正在起作用的原因.

编辑:根据Bo Persson,为什么它在这种情况下工作

os << endl; 是另一个操作符调用,实际上通过将其置于"预期返回值"(可能是寄存器)来返回操作系统.当代码返回另一个级别为main时,对os的引用仍然存在

  • 这里没有隐含的`int`.它被明确指定为返回`ostream&`.因此,如果没有`return`语句,您可以在函数之后获得堆栈中正确位置的任何junks.事实上,在那里使用`os << endl`,垃圾是不会导致崩溃的东西. (4认同)
  • @Dave - `os << endl;`是另一个操作符调用,实际上通过将其放在"预期返回值的地方"(可能是寄存器)来返回`os`.当代码返回另一个级别为main时,对`os`的引用仍然存在. (4认同)
  • 从N3337(c ++ 11之后的初稿)`6.6.3`:"函数末尾的流程等同于没有值的`return`;这会导致值返回函数中的未定义行为." 我想编译器可能不认为这是一个错误的原因是有其他合法的方法来退出函数(例如抛出异常). (3认同)
  • @honk在C++中没有隐含的`int`.无法从非```函数返回一些东西,只是未定义的行为,句号. (2认同)
  • @Dave你有*有*.只是一些带有任何选项的编译器可能不会告诉你,你做错了. (2认同)
  • @Dave:在C中它是UB如果你试图使用这个值,在C++中它是UB,如果你"退掉"函数的结尾而不返回. (2认同)