istream_iterator不进行零初始化

时间:2016-06-07 14:30:24

标签: c++ istream istream-iterator extraction-operator

这是Minimal, Complete, Verifiable Example我明白这不是copacetic。无论如何,给出结构:

UIViewController

我可以做以下事情:

presentViewController(_:animated:)

然而,这给了我结果:

  

-1215720516 1
  2 1
  2 3
  4 3
  4 5
  6 5
  6 7
  8 7
  8 9
  0 9

要初始化struct Foo { int even; int odd; }; istream& operator>>(istream& lhs, Foo& rhs) { int input; lhs >> input; (input % 2 == 0 ? rhs.even : rhs.odd) = input; return lhs; } ,我可以编写代码:

stringstream bar("1 2 3 4 5 6 7 8 9 0");

for (const auto& i : vector<Foo>{istream_iterator<Foo>(bar), istream_iterator<Foo>()}) {
    cout << i.even << ' ' << i.odd << endl;
}

这给出了我的预期结果:

  

0 1
  2 0
  0 3
  4 0
  0 5
  6 0
  0 7
  8 0
  0 9
  0 0

我知道有一个不完全覆盖变量的提取运算符是粗略的。这最初源于我的回答here和我的问题here,在我看来,它更自然地期望对读取之间的变量进行零初始化。在任何情况下,是否可以使用Foo使得变量在读取之间进行零初始化,或者我必须使用for(Foo i{}; bar >> i; i = Foo{}) { cout << i.even << ' ' << i.odd << endl; } - 循环吗?

2 个答案:

答案 0 :(得分:2)

  

在我的脑海中有一个更自然的期望,即在读取之间对变量进行零初始化

这是一个不正确的期望。 operator>>完全完全负责初始化对象。您不能假设该对象先前已默认/值初始化。一个非常标准的用例是读取while循环中的所有对象:

Foo foo;
while (std::cin >> foo) { ... }

第二次通过,foo将具有旧的价值 - 这里没有任何归零。因此,您需要确保在操作员返回时,新对象完全由您设置。

最简单的方法是首先对其进行初始化:

istream& operator>>(istream& lhs, Foo& rhs) {
    int input;    
    lhs >> input;
    rhs = Foo{}; // <== add this
    input % 2 == 0 ? rhs.even : rhs.odd) = input;
    return lhs;
}

或者你可以手动写两个:

if (input % 2 == 0) {
    rhs.odd = 0;
    rhs.even = input;
}
else {
    rhs.odd = input;
    rhs.even = 0;
}

或聚合初始化每个案例:

rhs = input % 2 == 0 ? Foo{input, 0} : Foo{0, input};

无论如何,operator>>负责将您想要归零的值归零。

答案 1 :(得分:1)

  

是否可以使用istream_iterator使得变量在读取之间进行零初始化?

如果您查看internals of the istream_iterator,它会有以下内部状态。

private:
  istream_type* _M_stream;
  _Tp       _M_value;
  bool      _M_ok;

默认构造_M_value的位置。

当它使用++ / ++时,它调用_M_read(),它的实现中有以下相关的行。

*_M_stream >> _M_value;

因此迭代器本身永远不会在你的extrator之外触及你的Foo的状态,并且_M_value在调用之间被重用。即你需要自己以某种方式初始化它。我认为operator>>是一个合理的地方。