为什么存在 C++11 std::initializer_list 构造函数重载规则
Why do the C++11 std::initializer_list constructor overloading rules exist?
我似乎想不出也找不到以下代码的理由:
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)
根据您使用的构造方法({}
vs ()
)调用不同的函数,这对我来说似乎非常反常。为什么std::initializer_list
优于其他与给定参数完美匹配的功能?我知道上面的构造函数为什么会这样。我能看到的这种行为的唯一好处是,您可以使用特定值初始化容器,并且只需要一对大括号; 2
在 C++11 中被弃用,大概是因为这个变化,但我仍然无法推理std::vector<int> a{1,2}
与std::vector<int> a{{1,2}}
.但是,至少对我来说,这肯定不会超过这带来的歧义和过载分辨率的变化。根据Scott Meyers在Effective Modern C++中的说法,std::make_unique
和std::make_shared
需要明确说明哪种形式用于构造作为其接口的一部分(因为过载分辨率)。这对我来说似乎很荒谬。
承认我一定错过了什么,但我只是不确定它是什么。请注意,我只是以std::vector
为例,我询问的是一般的功能。
这在 C++11 中非常有趣:原因是支撑参数没有类型。但是有一个例外,我不清楚它为什么存在:"auto"变量是唯一允许将支撑参数隐式视为初始值设定项列表的变量。但是,如果您有自动函数类型,则不允许返回此初始值设定项列表。
现在,你是对的:初始值设定项列表的一个好处是你可以使用特定值初始化容器。这是一个值得改变的巨大好处!
在初始值设定项列表之前,创建一个模板,允许您使用不同的值初始化容器中的每个类需要严厉的解决方案,例如接收每个值的 std::vector,或构造一个"空"模板类,然后打孔每个值。
另一件事是初始值设定项列表允许您以比使用从 C 导入的这种可怕的<cstdarg>
更安全的方式为 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;
}
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- std::list 模板是否需要其实例类型中的复制构造函数(或等效项)?
- 错误:没有用于初始化'List<double>::node'的匹配构造函数
- 'list::list'命名构造函数,而不是类型
- 使用 boost 将 std::list 传递给构造函数,list_of不编译
- std::list 的默认构造函数可以<int>抛出吗?
- std::list<std::unique_ptr>:空初始值设定项列表与默认构造函数
- 以vector、list或map为成员的类需要复制构造函数
- 为什么std::list中的单参数构造函数定义为显式