【问题标题】:Overloaded ostream operator segmentation fault if no endl如果没有 endl,则重载 ostream 运算符分段错误
【发布时间】:2013-03-25 04:43:55
【问题描述】:
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;
}

在上面的代码中,如果把标记的行去掉,就会出现段错误错误,有人能解释一下原因吗?

【问题讨论】:

  • 为什么没人关心检查有问题的代码?编译器应该警告你这样的错误 - “...警告:在函数中没有返回语句返回非 void [-Wreturn-type]”见liveworkspace.org/code/2ygK20$1 } ^

标签: c++ vector operator-overloading ostream


【解决方案1】:
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?
}

不是强制性的。段错误是因为你没有返回os

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

如果您不返回 ostream,这是未定义的行为。 endl 正在刷新您的 os 此处。这就是它看起来有效的原因。

编辑:根据 Bo Persson 的说法,为什么它在这种情况下有效

操作系统

【讨论】:

  • 这里没有隐式返回int。它被明确指定为返回ostream&amp;。因此,如果没有return 语句,您将在函数之后得到恰好位于堆栈上正确位置的任何垃圾。碰巧有os&lt;&lt;endl,那个垃圾不会导致崩溃。
  • @honk C++ 中没有隐式的int。未能从非void 函数返回某些内容只是未定义的行为,句号。
  • @Dave 你确实拥有。只是一些带有任何选项的编译器可能不会告诉你你做错了。
  • 来自 N3337(c++11 之后的初稿)6.6.3:“从函数末尾流出相当于没有值的 return;这会导致值中的未定义行为-返回函数。”我猜编译器可能不认为这是一个错误的原因是还有其他合法的方法可以退出函数(例如抛出异常)。
  • @Dave - os &lt;&lt; endl; 是另一个运算符调用,它通过将os 放置在“预期返回值的位置”(可能是寄存器)来实际返回。当代码返回另一个级别到 main 时,对 os 的引用仍然存在。
猜你喜欢
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 2014-11-30
  • 2013-10-10
  • 1970-01-01
  • 2014-04-24
相关资源
最近更新 更多