对于 initiailzer_list
,Cpp 为什么只提供默认构造函数:cppreference;
那我来初始化一下 vector:
vector<int> vec(initializer_list<int>()); // "expression must have class type" warning when using vec
为啥又不行呢?
为什么改成 {} 就可以了呢?
vector<int> vec(initializer_list<int>{}); // OK
{} 是脱离于构造函数之外的嘛?
那为什么用 {} 初始化有时候也必会调用对应的构造函数呢?
struct A{
A(int a, int b){this->a = 2*a; this->b = 2*b;}
int a;
int b;
};
A a{1, 2}; // (2, 4)
brace(list) initialization 的设计到底是为了什么?
1
AngelCriss 2018-09-20 22:26:18 +08:00 via Android
看了几遍都没看明白你在说啥。。
|
2
HHehr0ow 2018-09-20 22:30:57 +08:00
most vexing parse 了解一下
|
3
v2byy 2018-09-20 22:51:55 +08:00 via iPad
大括号初始化是 cpp11 引入的统一化初始化方式。具体建议你看下 effective modern cpp
|
4
innoink 2018-09-20 23:08:00 +08:00 via Android
initializer_list<int>()
被解析成了一个函数 你放个 int()也是一样 老问题了 |
5
innoink 2018-09-20 23:09:20 +08:00 via Android
被解析成了函数声明
|
6
chengluyu 2018-09-20 23:10:51 +08:00
Type variable();
上面的代码究竟是初始化了 variable 还是声明了一个叫 variable 的函数? 想想这个问题你就明白了。 |
7
innoink 2018-09-20 23:44:44 +08:00
如果你用过 tsd::function,就会知道类似于 int(char)这种是函数类型
因此 initializer_list<int>() 被解析成了类型名,即一个参数为空,返回值为 initializer_list<int>的函数类型 vector<int> vec(initializer_list<int>()); 则被解析成了一个 返回值为 vector<int>、参数为上一行的函数类型 的一个函数声明 你可以试着跑一下这个程序: #include <iostream> #include <vector> #include <string> int f() { std::cout << "111"; return 0; } std::vector<int> v(int()) { std::cout << "222"; std::vector<int> x; return x; } int main() { v(f); return 0; } |
8
gnaggnoyil 2018-09-21 00:54:12 +08:00
>那为什么用 {} 初始化有时候也必会调用对应的构造函数呢?
对于非 aggragate,并且具有非默认构造函数的类型,list initialization 本来就会调用它们的(隐式)构造函数. >brace(list) initialization 的设计到底是为了什么? 1.避免 most vexing parse. 2.它为 aggragate(以及数组)和非 aggragate 类型提供了统一的并且有实际作用的初始化 syntax,因为 aggragate 类型所拥有的构造函数只有隐式生成的那几个,没法用来初始化其所拥有的成员变量;而至于数组则连隐式生成的构造函数都没有.在写泛型代码或者修改类的定义的时候这种统一性会特别好使.事实上如果我没记错的话 C++标准中第二个能用于初始化一个 aggragate 类型对象的成员变量的语言特性还是 C++2a 中新加入的 designated initializers. 3.标准中明确禁止 list initialization 在参数匹配的时候基本类型的参数出现产生精度损失的 narrowing conversion,可以帮助避免很多 bug. 4.花括号列表中的表达式其可观察行为一定是表现的好像是从左到右被依次执行的,或者更准确的说,处于列表较后面的表达式一定 sequenced after 较前面的表达式.这个特性配合 pack expansion 可以简化很多变长模板的写法. |
9
dangyuluo 2018-09-21 02:02:44 +08:00
读一下 Effective Modern C++,Item14 还是 17 来着,很详细。
|