C++17 中的聚合初始化可以执行复制省略吗?

Jia*_* Xu 0 c++ aggregate-initialization copy-elision c++17

鉴于:

//C++17
#include <string>
struct Foo {
    int i;
    std::string str;
};

int main() {
    Foo foo{1, std::string("Hello, world!")};
}
Run Code Online (Sandbox Code Playgroud)

可以Foo::i直接Foo::str1std::string(...)初始化,而不是复制到其中,并解释为什么可以/不能使用 C++17 标准(可能是一些用于测试目的的代码)?

如果不能,需要多少份?

Bar*_*rry 6

聚合初始化基本上执行逐元素复制初始化。所以这:

\n\n
struct Foo {\n    int i;\n    std::string str;\n};\n\nFoo foo{1, std::string("Hello, world!")};\n
Run Code Online (Sandbox Code Playgroud)\n\n

执行与以下相同的初始化:

\n\n
int i = 1;\nstd::string str = std::string("Hello, world!");\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们在 C++17 中有一条新规则:

\n\n
\n

如果初始值设定项表达式是纯右值,并且源类型的 cv 未限定版本与目标类是同一类,则初始值设定项表达式用于初始化目标对象。[\xe2\x80\x89示例: T x = T(T(T()));调用T默认构造函数进行初始化x\xe2\x80\x94\xe2\x80\x89结束示例\xe2\x80\x89]

\n
\n\n

这意味着第二次初始化的行为必须像您编写的那样:

\n\n
std::string str("Hello, world!");\n
Run Code Online (Sandbox Code Playgroud)\n\n

即零副本。

\n\n
\n\n

以下示例很好地演示了新规则:

\n\n
struct X {\n    X(int ) { }\n    X(X&& ) = delete;\n};\n\nstruct Y {\n    X x;\n};\n\nint main() {\n    Y y{X{4}}; // ill-formed in C++14 due to deleted move ctor\n               // ok in C++17, no move required\n}\n
Run Code Online (Sandbox Code Playgroud)\n