【问题标题】:C++ Input stream: operation order in Solaris vs. LinuxC++ 输入流:Solaris 与 Linux 中的操作顺序
【发布时间】:2015-03-13 05:23:43
【问题描述】:

我有一个非常简单的测试程序,它使用 istringstreams 从 std::string 中读取整数。代码是:

std::map<int, int> imap;
int idx, value;
std::string str("1 2 3 4 5 6 7 8");
istringstream is(str);
while(is >> idx >> imap[idx]){
    cout << idx << " " << imap[idx] << endl;
}
cout << endl;

std::map<int, int>::iterator itr;
for(itr = imap.begin(); itr != imap.end(); itr++){
    cout << itr->first << " " << itr->second << endl;
}

当我在 Solaris 10 上运行它时,它会产生以下输出:

1 2
3 4
5 6
7 8

1 2
3 4
5 6
7 8

但是,当我在 CentOS 7 下运行它时,我得到:

1 0
3 0
5 0
7 0

1 4
3 6
5 8
7 0
4204240 2

有谁知道为什么它在 Linux 和 Solaris 下会有所不同?它显然是在读入地图索引之前将值读入地图,但我不知道为什么。我可以通过稍微更改代码使其在 Linux 下工作:

std::map<int, int> imap;
int idx, value;
std::string str("1 2 3 4 5 6 7 8");
istringstream is(str);
while(is >> idx >> value){
    imap[idx] = value;
    cout << idx << " " << imap[idx] << endl;
}

std::map<int, int>::iterator itr;
for(itr = imap.begin(); itr != imap.end(); itr++){
    cout << itr->first << " " << itr->second << endl;
}

我知道这是一个有效的解决方案,但我周围的人想知道为什么它会有所不同。我们正在从 Solaris 迁移到 Linux,当这样的事情出现时,他们想知道原因。我不知道为什么,所以我请求指导。

【问题讨论】:

  • 它在一台机器上工作而不是在另一台机器上工作的事实意味着它是未定义的行为
  • 与此处发布的类似操作顺序陷阱一样,表达式is &gt;&gt; idx &gt;&gt; imap[idx] 多次评估变量,同时至少修改一次。见stackoverflow.com/questions/4176328

标签: c++ linux stream solaris


【解决方案1】:
is >> idx >> imap[idx]

这个表达式等价于

operator>>(operator>>(is, idx), imap.operator[](idx))

对同一函数的参数的计算相对于彼此是无序的; operator&gt;&gt;(is, idx)imap.operator[](idx) 可能首先被评估(也就是说,is &gt;&gt; idximap[idx] 可能首先被评估)。如果后者先求值,则结果是一个左值,指的是映射中idxold值对应的值;正是这个值将被第二次读取覆盖,而不是与 idxnew 值对应的值。

修改后的代码通过确保在访问 imap[idx] 之前读取 idx 来解决此问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    相关资源
    最近更新 更多