Pet*_*Lee 5 c++ initialization initializer-list
我试图了解 C++ STL 容器的初始化。这是我的噩梦:
vector<int> V0 ({ 10, 20 }); // ok - initialized with 2 elements
vector<int> V1 = { 10, 20 }; // ok - initialized with 2 elements
vector<int> V2 = {{ 10, 20 }}; // ok - initialized with 2 elements
vector<int> V3 = {{ 10 }, 20 }; // ok - initialized with 2 elements
vector<int> V4 { 10, 20 }; // ok - initialized with 2 elements
vector<int> V5 {{ 10, 20 }}; // ok - initialized with 2 elements
vector<int> V6 {{ 10 }, 20 }; // ok - initialized with 2 elements
queue<int> Q0 ({ 10, 20 }); // ok - initialized with 2 elements
// queue<int> Q1 = { 10, 20 }; // compile error
// queue<int> Q2 = {{ 10, 20 }}; // compile error
// queue<int> Q3 = {{ 10 }, 20 }; // compile error
// queue<int> Q4 { 10, 20 }; // compile error
queue<int> Q5 {{ 10, 20 }}; // ok - initialized with 2 elements
// queue<int> Q6 {{ 10 }, 20 }; // compile error
Run Code Online (Sandbox Code Playgroud)
我们正在谈论 C++11。
我做了一些研究,这里是我的问题:
queue<T>的initializer_list构造函数造成的。请参阅vector<T>:http : //www.cplusplus.com/reference/vector/vector/vector/和queue<T>:
http: //www.cplusplus.com/reference/queue/queue/queue/ 我说得对吗?V0到 的所有向量V6,我明白V0, V1, V4。有人可以帮我了解V2,V3,V5和V6?Q0或Q5。有人能帮我吗?我也在阅读 Mike Lui 的文章:Initialization in C++ is Seriously Bonkers。我想和你们分享一下,但是有没有一种快速的方法可以帮助我理解这个噩梦?:-)
没有任何“噩梦”。你只需要阅读你写的东西。更具体地说,您必须从外向内系统地处理规则。
vector<int> V0 ({ 10, 20 });
Run Code Online (Sandbox Code Playgroud)
调用一个vector构造函数(这就是()意思),传递给它一个花括号初始化列表。因此,它将选择一个接受一个值的构造函数,但只有第一个参数可以由包含整数的 2 元素花括号初始化列表初始化的构造函数。比如包含的initializer_list<int>构造函数vector<int>。
vector<int> V1 = { 10, 20 };
Run Code Online (Sandbox Code Playgroud)
列表初始化(这就是直接使用花括号初始化列表初始化事物时发生的情况)。在列表初始化规则下,首先考虑采用单个initializer_list参数的类型的所有构造函数。系统尝试直接使用braced-init-list 初始化这些构造函数;如果它可以使用候选构造函数之一成功,则调用该构造函数。
显然,您可以initializer_list<int>从整数的 2 元素花括号初始化列表中初始化 。这是 中唯一的initializer_list构造函数vector,因此它被调用。
vector<int> V2 = {{ 10, 20 }};
Run Code Online (Sandbox Code Playgroud)
仍然是列表初始化。再次initializer_list考虑与括号初始化列表中的值匹配的构造函数。但是,花括号初始化器列表中的“值”本身就是另一个花括号初始化器列表。int不能从 2 元素的花括号初始化列表初始化,因此initializer_list<int>不能由{{10, 20}}.
由于不能initializer_list使用构造函数,因此所有构造函数都在正常的函数重载解析规则下被考虑。在这种情况下,(外部)花括号初始化列表的成员被视为该类型构造函数的参数。外层括号初始化列表中只有一个值,因此只考虑可以使用一个参数调用的构造函数。
系统将尝试使用内部花括号初始化列表初始化所有此类构造函数的第一个参数。并且有一个构造函数,其参数可以由整数的 2 元素花括号初始化列表初始化。即initializer_list<int>构造函数。也就是说,虽然initializer_list<int>不能被 初始化{{10, 20}},但可以被 初始化{10, 20}。
vector<int> V3 = {{ 10 }, 20 };
Run Code Online (Sandbox Code Playgroud)
同样,仍然列出初始化。因此,我们首先尝试将完整的花括号初始化列表应用于initializer_list该类型的任何构造函数。可以initializer_list<int>从{{10}, 20}? 是的。所以这就是发生的事情。
为什么这样做?因为任何T可复制/可移动的类型始终可以从包含该类型的某些值的花括号初始化列表进行初始化。也就是说,如果T t = some_val;有效,那么也一样T t = {some_val};(除非T有一个带 的initializer_list构造函数T,这肯定很奇怪)。如果T t = {some_val};有效,那么也一样initializer_list<T> il = {{some_val}};。
vector<int> V4 { 10, 20 }; // ok - initialized with 2 elements
vector<int> V5 {{ 10, 20 }}; // ok - initialized with 2 elements
vector<int> V6 {{ 10 }, 20 }; // ok - initialized with 2 elements
Run Code Online (Sandbox Code Playgroud)
它们与 1、2 和 3 相同。列表初始化通常称为“统一初始化”,因为直接使用括号初始化列表和使用= braced-init-list. 唯一不同的是,是否选择了显式构造函数,或者是否使用auto了支撑初始化列表中的单个值。
queuesinitializer_list构造函数没有“丢失”。它不是故意存在的,因为queue它不是容器。它是一种容器适配器类型。它存储一个容器并调整容器的接口以限制队列操作:push、pop 和 peek。
所以这些都不应该起作用。
queue<int> Q0 ({ 10, 20 });
Run Code Online (Sandbox Code Playgroud)
这调用了queue<int>使用常规旧重载解析的构造函数,就像V0. 唯一的区别是它选择的构造函数是采用队列容器类型的构造函数。由于您没有指定容器,它使用默认值: std::deque<int>,它可以从两个整数的花括号初始化列表构造。
queue<int> Q5 {{ 10, 20 }};
Run Code Online (Sandbox Code Playgroud)
一样的情况V2。上没有 initializer_list 构造函数queue,因此它的作用完全类似于Q0:使用重载决议来选择一个构造函数,其参数可以采用 2 个整数的花括号初始化列表。
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |