C++ 为什么C++;11 std::初始值设定项\列表构造函数重载规则是否存在?
我似乎想不出也找不到以下代码的理由:C++ 为什么C++;11 std::初始值设定项\列表构造函数重载规则是否存在?,c++,c++11,initializer-list,C++,C++11,Initializer List,我似乎想不出也找不到以下代码的理由: std::vector<int> a{1,2} // calls (7) std::vector<int> a(1,2) // calls (2) // constructors from http://en.cppreference.com/w/cpp/container/vector/vector vector( std::initializer_list<T> init, const Alloca
std::vector<int> a{1,2} // calls (7)
std::vector<int> a(1,2) // calls (2)
// constructors from http://en.cppreference.com/w/cpp/container/vector/vector
vector( std::initializer_list<T> init,
const Allocator& alloc = Allocator() ); // (7)
explicit vector( size_type count,
const T& value = T(),
const Allocator& alloc = Allocator()); // (2)
std::vector a{1,2}//调用(7)
向量a(1,2)//调用(2)
//来自http://en.cppreference.com/w/cpp/container/vector/vector
向量(std::初始值设定项\列表初始值,
常量分配器&alloc=Allocator());//(7)
显式向量(大小\类型计数,
常数T&value=T(),
常量分配器&alloc=Allocator());//(2)
根据您使用的构造方法调用不同的函数({}
vs()
),这在我看来非常反常。为什么std::initializer\u list
比其他完全匹配给定参数的函数更受欢迎?我知道上面的构造函数2
在C++11中被弃用,可能是因为这个变化,但我仍然无法解释为什么会这样。我看到的这种行为的唯一好处是,您可以使用特定的值初始化容器,并且只需要一对大括号<代码>标准::向量a{1,2}vs标准::向量a{1,2}
。但是,至少对我来说,这肯定不会超过它所带来的模糊性和对超负荷解决方案的改变。根据Scott Meyers在现代C++中的有效性,我承认我肯定错过了什么,但我不确定是什么。请注意,我刚刚使用了
std::vector
作为一个示例,我想了解一下该特性的一般情况 这在C++11中非常有趣:原因是大括号参数没有类型。但有一个例外,我也不清楚它存在的原因:“auto”变量是唯一允许将大括号参数隐式视为初始值设定项列表的变量。但如果您有自动函数类型,则不允许返回此初始值设定项列表
现在,您是对的:初始化列表的一个好处是您可以使用特定的值初始化容器。这是值得改变的巨大好处
在初始化器列表之前,制作一个模板,允许您使用不同的值初始化容器中的每个类,这需要严格的解决方案,比如接收带有每个值的std::vector,或者构造一个“空”模板类,然后冲压每个值
另一个问题是,初始化列表允许您以更安全的方式创建C++的ValueCube函数,而不是使用从C导入的可怕的<代码> <代码>(尽管变量模板更好)
想玩一下组合吗#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
vector<int> func (const vector<int> &a) { //works
//auto func (const vector<int> &a) -> vector<int> { //works
//auto func (const vector<int> &a) { //don't even compile, "returns a initializer list" error
for (int i: a) {
cout << "My " << i << endl;
}
return {20 , 30};
}
int main()
{
//play with anonymous functions
auto y = [ ](vector<int> e) { return e; }; //works
vector<int> x = y({20, 30});
//auto y = [ ](){ return {20, 30}; }; //don't even compile, "returns a initializer list" error
//vector<int> x = y();
//play with initialization
//vector<int> x = {2,2,20,30}; //works
//vector<int> x{2,2,20,30}; //works
//auto x = vector<int>{2,2,20,30}; //works
//Bellow, a common mistake of people initializing a int to a auto, like auto x = { 1 }
//auto x = {2,2,20,30}; //wrong, but compiles, its a initializer list
//auto x{2,2,20,30}; //wrong, but compiles, its a initializer list
//Play with return types
//vector<int> x = func(vector<int>(2,2)); //works only with vector<int> and auto with trailing type
//vector<int> x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type
//vector<int> x{func(vector<int>(2,2))}; //works only with vector<int> and auto with trailing type
//auto x = func(vector<int>(2,2)); //works only with vector<int> and auto with trailing type
//auto x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type
cout << typeid(x).name() << endl;
for (int i: x) {
cout << "My " << i << endl;
}
return 0;
}
#包括
#包括
#包括
使用名称空间std;
向量func(const向量&a){//works
//自动函数(常量向量&a)->向量{//works
//auto-func(const-vector&a){//甚至不编译,“返回初始值设定项列表”错误
对于(int i:a){
如果std::vector a{1,2,3};
,std::vector a{1,2,3,4};
,std::vector a{1,2,3,4,5};
都调用初始值设定项列表构造函数,但std::vector a{1,2};
不调用。@t.C.这就是为什么我认为它应该是std::vector a{1,2,3}
没有优先考虑std::initializer\u list
构造函数。另外,我不知道你为什么认为#2不受欢迎。事实并非如此。啊,C++11中的C++03签名被一分为二。原始设计选择的理由可以在@user1520427中找到。默认参数在C++11中被删除,下面的构造函数添加了接受计数的ctor。它们一起模拟了前面的单个构造函数。我相信所做的更改是为了让您可以使用不可复制类型的count
实例初始化vector
。这很有趣,我想这可以解释为什么我们最终会出现这种行为(因为括号内的参数没有类型)。我当然认为,不幸的是,标准委员会没有认识到这个问题,我认为他们应该使用“双括号”,而不是处理std::initializer_list
不同的重载解决方案解决方案。不过,我不明白他们为什么故意想要这种行为。统一初始化本可以如此优雅。