引入的目的或者主要用处
- 如果我们的函数无法事先知道函数要传入的参数是多少,是什么类型,即要定义未知数量,未知类型的形参,要怎么定义呢,
一般是用省略号形参来定义,如:printf(char *format...)
c++11为我们再提供两种主要的方法:- 可变参数模板,它和省略号差不多,但还有更加强大的用处
- 如果传入的参数类型相同,但是数量不定的话,那就是我们的initializer_list了
变量或者对象的定义常用的大括号,中挂号,赋值符号
Rect r1 = {3, 7, 20, 50};
Rect r2{3, 7, 20, 50};
int a[6] = {0, 1, 2, 0, 1, 2};c++11提出了Unifrom Initialization(一致性初始化)的概念,也就是初始化可以都用一样的形式,大括号的内容就是initializer_list
double b{9.9}
int values[] v{0, 1, 2, 0, 1, 2};
vectorcities{"beijing", "shanghai"};
initializer_list的定义和使用
这个是一个标准库模板类,它内部使用的是array,比较简单
需要注意的是
1.拷贝或者复制是浅拷贝,两个对象共享元素
2.对象中的元素永远是const,我们无法改变内部的值
- 对于参数数量不定的举个代码:
#include <iostream>
#include <initializer_list>
using namespace std;
void error_msg(int ErrCode, initializer_list<string> il)
{
cout << "errno(" << ErrCode << "): ";
for (auto beg = il.begin(); beg != il.end(); ++beg)
cout << *beg << " " ;
cout << endl;
}
int main()
{
error_msg(2, {"ENOENT", "No such file or directory!"});
}
运行结果:
- 一致性初始化
初始化是编译器做的工作,比如定义变量complex<double> c{5.6, 6.7}
,编译器会生成initializer_list< double >,调用构造函数时编译器会分解元素并
逐一传递给函数,当然如果构造函数就有用initializer_list做参数的,那就直接传进去就可以,不需要分解
现在的stl标准库都有这种构造,比如vector:
vector(initializer_list<value_type> __l, const allocator_type& __a = allocator_type())
那么可以像数组那样定义而不用一个个append:
vector<int> a{1, 2, 3, 4, 5, 6, 7};
参考
- 侯捷老师的课程:b站侯捷c++11
- C++ Primer, Fifth Edition.pdf