c++ - 海湾合作委员会错误?链接方法,断序列点

标签 c++ gcc compiler-bug

我已经调试了一段时间的程序,最终发现错误是由于引用没有像我想象的那样更新。

这是一个显示我遇到的问题的示例:

#include <iostream>
using namespace std;

struct Test {
    Test& set(int& i){ i = 10; return *this; }
    Test& print(const int& i){ cout << i << endl; return *this; }
};

int main(void){
    int i = 0;
    Test t;

    t.set(i).print(i + 5);

    return 0;
}

我原以为这里的 print() 方法会输出 15,但结果却是 5。

编辑:10 天后,我才意识到使用 clang 输出 15!这是 GCC 中的错误吗?

最佳答案

让我试着解释一下 C++11 标准。在 §1.9/15 中它说:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

当然 int是标量类型,t.set(i).print(i + 5);包含对 i 的副作用在 set()和值(value)计算i + 5 ,所以如果没有另外说明,行为确实是未定义的。阅读第 5.2.5 节(“类成员访问”),我找不到关于 . 的序列的任何注释。运算符(operator)。 [但请参阅下面的编辑!]

请注意,当然可以保证 set()print() 之前执行因为后者接收前者的返回值作为(隐式 this )参数。 这里的罪魁祸首是 print 的值计算的参数是 unsequenced 相对于 set 的调用不确定地排序.

编辑:在阅读了您(@Xeno's)评论中的答案后,我重新阅读了标准中的段落,事实上它后来说:

Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

因为 indeterminately sequenced 不是 unsequenced(“未排序评估的执行可以重叠”,第 1.9/13 节),这确实不是未定义的行为,而是“只是”未指定的行为,这意味着 15 和 5 都是正确的输出。

所以当<表示“之前排序”和~表示“不确定排序”,我们有:

(value computations for print()'s arguments ~ execution of set()) < execution of print()

关于c++ - 海湾合作委员会错误?链接方法,断序列点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21611215/

相关文章:

c++ - std::chrono::time_point线程安全吗?

c++ - 如何从指向 vector 迭代器的指针中找到索引

c - 尽管包含 'strnlen',但未定义对 "string.h"的引用

c# - (this == null) 在 C# 中!

c++ - union 中的大括号或相等初始化器

generics - 通用静态方法调用无法在 Java 8 中编译

c++ - C++函数和奇怪的错误

C++ io 流与 mmap

gcc - 如何让编译器生成 "elf32-x86-64"格式的目标文件?

c++ - 在 Ubuntu 16.04 上编译 GCC 6.1