赋值运算符是 C++17 下的序列点吗?这种表达的结果会是什么?

Is assignment operator a sequence point under C++17? and what would be the result of this expression?

提问人:Maestro 提问时间:8/1/2022 最后编辑:Maestro 更新时间:8/2/2022 访问量:137

问:

建议不要在单个表达式中多次修改对象,也不要在同一表达式中修改对象后再使用它。

 int i = 0;
 ++++i; // UB

 ++i = i++; // OK?
  • 我认为最后一个表达式是 C++17 标准之前的 UB,但现在我想没关系,因为赋值运算符已成为序列点。

那么你怎么看?你能向我解释最后一个表达式中的值应该是什么吗?i++i = i++;

我知道这样做的设计很糟糕,但这只是为了教育目的。谢谢。

  • 当我针对 C++17 或 C++20 进行编译时:我仍然收到相同的警告:g++ main.cpp -std=c++17 -o prog -Wall -pedantic

    ++i = i++;
    

这是 GCC 的输出:

main.cpp: In function ‘int main()’: main.cpp:12:12: warning: operation on ‘i’ may be undefined [-Wsequence-point] 12 | ++i = i++; | ~^~.

C++ C++17 赋值运算符 序列点

评论

2赞 user17732522 8/1/2022
我不知道你为什么认为那是UB。必须在值计算之前对预增量的副作用进行排序,在该值计算之后必须对第二个预增量的副作用进行排序。(从C++11开始就适用了,在此之前它是不同的。++++i;

答:

3赞 lorro 8/1/2022 #1

现在没有序列点:我们有序列之前和之后序列。当您有呼叫(或任何其他呼叫 - 内置或用户定义的呼叫)时,右侧在左侧之前排序。所以在 C++ 17 中有效,在 sequenced-before 中。operator=operator@=operator=++i = i++i++++i

在 C++17 之前,正如你所写的,它是 UB。

评论

0赞 lorro 8/1/2022
@user17732522 已添加,谢谢。至于 C++ 之前的 17,它也在问题中(OP 认为它是 UB),但明确这一点是有道理的。
0赞 user17732522 8/1/2022
我可能太迂腐了,但作为另一个澄清,内置赋值运算符不是 s,也不涉及函数调用。(其他运营商也一样。operator=
0赞 bolov 8/1/2022
您可能想添加定义明确并且一直如此。++++i
1赞 user17732522 8/2/2022
@Maestro GCC 的开发人员决定保留警告,尽管该行为现在已经明确定义。我认为他们的理由是不应该编写这样的代码,并且不鼓励编写在更改标志时会损坏的代码。有一个错误报告。让我看看我能不能再找到它......-std
1赞 user17732522 8/2/2022
@Maestro 它实际上是这样记录的,见 gcc.gnu.org/onlinedocs/gcc/Warning-Options.html-Wsequence-point