可以在 c++17 的聚合初始化中执行复制省略吗?
Can copy elision be perfomed in aggregate initialization in c++17?
鉴于:
//C++17
#include <string>
struct Foo {
int i;
std::string str;
};
int main() {
Foo foo{1, std::string("Hello, world!")};
}
Foo::i
和 Foo::str
可以直接从 1
和 std::string(...)
初始化而不是复制到它们中,并解释为什么 can/can 不使用C++17 标准(可能是一些用于测试目的的代码)?
如果不能,需要多少份?
聚合初始化基本上执行逐元素复制初始化。所以这个:
struct Foo {
int i;
std::string str;
};
Foo foo{1, std::string("Hello, world!")};
进行与以下相同的初始化:
int i = 1;
std::string str = std::string("Hello, world!");
我们在 C++17 中有 a new rule 表示:
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object. [ Example: T x = T(T(T()));
calls the T
default constructor to initialize x
. — end example ]
这意味着第二次初始化的行为必须像您编写的那样:
std::string str("Hello, world!");
即零拷贝。
以下示例很好地演示了新规则:
struct X {
X(int ) { }
X(X&& ) = delete;
};
struct Y {
X x;
};
int main() {
Y y{X{4}}; // ill-formed in C++14 due to deleted move ctor
// ok in C++17, no move required
}
鉴于:
//C++17
#include <string>
struct Foo {
int i;
std::string str;
};
int main() {
Foo foo{1, std::string("Hello, world!")};
}
Foo::i
和 Foo::str
可以直接从 1
和 std::string(...)
初始化而不是复制到它们中,并解释为什么 can/can 不使用C++17 标准(可能是一些用于测试目的的代码)?
如果不能,需要多少份?
聚合初始化基本上执行逐元素复制初始化。所以这个:
struct Foo {
int i;
std::string str;
};
Foo foo{1, std::string("Hello, world!")};
进行与以下相同的初始化:
int i = 1;
std::string str = std::string("Hello, world!");
我们在 C++17 中有 a new rule 表示:
If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object. [ Example:
T x = T(T(T()));
calls theT
default constructor to initializex
. — end example ]
这意味着第二次初始化的行为必须像您编写的那样:
std::string str("Hello, world!");
即零拷贝。
以下示例很好地演示了新规则:
struct X {
X(int ) { }
X(X&& ) = delete;
};
struct Y {
X x;
};
int main() {
Y y{X{4}}; // ill-formed in C++14 due to deleted move ctor
// ok in C++17, no move required
}