我们知道这T v(x);被称为直接初始化,而T v = x;被称为复制初始化,这意味着它将构造一个临时T的x,将被复制/移入v(很可能被省略).
对于列表初始化,标准根据上下文区分两种形式.T v{x};称为直接列表初始化,T v = {x};称为复制列表初始化:
§8.5.4 [dcl.init.list] p1
[...]列表初始化可以在直接初始化或复制初始化上下文中进行; 直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化.[...]
但是,整个标准中只有两个引用.对于直接列表初始化,在创建像T{x}(§5.2.3/3)这样的临时表时会提到它.对于copy-list-initialization,它用于返回语句中的表达式,如return {x};(§6.6.3/2).
现在,下面的片段怎么样?
#include <initializer_list>
struct X{
X(X const&) = delete; // no copy
X(X&&) = delete; // no move
X(std::initializer_list<int>){} // only list-init from 'int's
}; …Run Code Online (Sandbox Code Playgroud) 作为一个更大项目的一部分,我正在玩std::tuple模板; 考虑以下代码:
template <typename ...T> void foo(tuple<T...> t) {}
void bar(tuple<int, char> t) {}
tuple<int, char> quxx() { return {1, 'S'}; }
int main(int argc, char const *argv[])
{
foo({1, 'S'}); // error
foo(make_tuple(1, 'S')); // ok
bar({1, 'S'}); // ok
quxx(); // ok
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据这个答案, C++ 17支持从复制列表初始化开始的元组初始化,但是由于我得到以下错误(GCC 7.2.0),所以似乎这种支持是有限的:
main.cpp: In function 'int main(int, const char**)':
main.cpp:14:17: error: could not convert '{1, 'S'}' from '<brace-enclosed initializer list>' to 'std::tuple<>'
foo({1, 'S'}); // error …Run Code Online (Sandbox Code Playgroud) c++ initializer-list variadic-templates uniform-initialization c++17