这个代码是否定义明确,无论复制省略?

Rus*_*lan 8 c++ undefined-behavior copy-elision

考虑以下代码:

#include <iostream>

struct Test
{
    int x;
    int y;
};

Test func(const Test& in)
{
    Test out;
    out.x=in.y;
    out.y=in.x;
    return out;
}

int main()
{
    Test test{1,2};
    std::cout << "x: " << test.x << ", y: " << test.y << "\n";
    test=func(test);
    std::cout << "x: " << test.x << ", y: " << test.y << "\n";
}
Run Code Online (Sandbox Code Playgroud)

人们会期望这样的输出:

x: 1, y: 2
x: 2, y: 1
Run Code Online (Sandbox Code Playgroud)

这确实是我得到的.但由于复制省略,可能out在内存中的同一位置in并导致最后一行输出x: 2, y: 2

我试着用gcc和铿锵既编译-O0-O3,结果却看起来像预期.

Sha*_*our 3

这是格式良好的代码,优化不能破坏格式良好的代码,因为它会违反as-if 规则。这告诉我们:

\n\n
\n

特别是,它们不需要复制或模拟抽象机的结构。相反,需要一致的实现来模拟(仅)抽象机的可观察行为,如下所述

\n
\n\n

复制省略除外:

\n\n
\n

[...]允许省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数有副作用。[。 ..]

\n
\n\n

但仍然必须遵循排序规则,如果我们查看标准草案,我们会发现赋值是在第 5.17 节评估左右操作数之后进行排序的:

\n\n
\n

在所有情况下,赋值都在右操作数和左操作数的值计算之后、赋值表达式的值计算之前进行排序

\n
\n\n

我们知道,相对于其他未通过 1.9 节中的函数调用专门排序的求值,函数体的排序是不确定的:

\n\n
\n

调用函数(包括其他函数调用)中的每个计算在被调用函数体执行之前或之后没有明确排序的,都相对于被调用函数的执行不确定地排序 9

\n
\n\n

不确定顺序意味着:

\n\n
\n

当 A 在 B 之前排序或 B 在 A 之前排序时,评估 A 和 B 的顺序是不确定的,但未指定是哪一个。[ 注意:不确定顺序的评估不能重叠,但可以先执行其中一个。\xe2\x80\x94结束注]

\n
\n