我似乎无法想到也找不到以下代码的理由:
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::initializer_list
比其他完全匹配给定参数的函数更受欢迎? 我知道构造函数。对于这种行为,我能看到的唯一好处是您可以使用特定值初始化容器,并且只需要一对大括号; 2
above 在 C++11 中被弃用,大概是因为这个变化,但我仍然无法解释为什么是这种情况std::vector<int> a{1,2}
对比std::vector<int> a{{1,2}}
.但是,至少对我来说,这肯定不会超过由此带来的歧义和重载解决方案的变化。根据 Effective Modern C++ 中的 Scott Meyers,std::make_unique
和 std::make_shared
需要明确说明使用哪种形式作为其接口(interface)的一部分进行构造(由于重载决议)。这对我来说似乎很荒谬。
我承认我一定遗漏了什么,但我不确定是什么。请注意,我刚刚使用了 std::vector
举个例子,我问的是一般的功能。
最佳答案
这对于 C++11 来说很有趣:原因是花括号参数没有类型。但这有一个异常(exception),我不清楚它存在的原因:“auto”变量是唯一允许将大括号参数隐式视为初始化列表的变量。但是如果你有一个自动函数类型,它不允许返回这个初始化列表。
现在,你是对的:初始化列表的一个好处是你可以用特定的值初始化一个容器。这是一个值得改变的巨大好处!
在初始化器列表之前,制作一个模板允许您使用不同的值初始化容器内的每个类需要严格的解决方案,比如接收一个带有每个值的 std::vector,或者构建一个“空”模板类,然后打洞之后的每个值。
另一件事是,初始化列表允许您以比使用这个可怕的 <cstdarg>
更安全的方式为 C++ 创建可变参数函数。从 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;
}
关于c++ - 为什么存在 C++11 std::initializer_list 构造函数重载规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28270217/