1 列表初始化语法 initializer_list<>
C++11中,集合(列表)的初始化已经成为C++语言的一个基本功能,这种初始化的方法被称为“初始化列表”(initializer list),例如:
#include <vector>
#include <map>
using namespace std;
int a[] = {1, 3, 5};
int b[]{2, 4, 6};
vector<int> c{1, 3, 5};
map<int, float> d =
{{1, 1.0f},
{2, 2.0f},
{5, 3.2f}};
这样一来,自动变量和全局变量的初始化在C++11中被丰富了,程序员可以使用以下几种形式完成初始化的工作 :
- 等号“=”加上赋值表达式(assignment-expression),比如 int a = 3 + 4;
- 等号“=”加上花括号式的初始化列表,比如 int a = {3 + 4};
- 圆括号式的表达式列表(expression-list),比如 int a (3 + 4);
- 花括号式的初始化列表,比如 int a {3 + 4};
后面2种形式也可以用于获取堆内存new操作符中,比如:
int* i = new int(1);
double* d = new double{1.2f};
自定义的类如果要使用初始化列表初始化,需要#include <initializer_list>
头文件,并且声明一个以initializer_list模板类为参数的构造函数:
#include <vector>
#include <map>
using namespace std;
enum Gender {
boy, girl
};
class People {
public:
People(initializer_list<pair<string, Gender>> l) { // initializer_list的构造函数
auto i = l.begin();
for (; i != l.end(); ++i)
data.push_back(*i);
}
private:
vector<pair<string, Gender>> data;
};
People ship2012 = {{"Garfield", boy}, {"HelloKitty", girl}};
同样的,函数的参数列表也可以使用初始化列表:
#include <initializer_list>
using namespace std;
void Fun(initializer_list<int> iv) { }
int main() {
Fun({1, 2});
Fun({}); // 空列表
}
可有接收任意个数的初始化值
void print(std::initializer_list<int> vals) {
for (auto p = vals.begin(); p != vals.end(); ++p) { // a list of values
std::cout << *p << "\n";
}
}
print({1, 3, 5, 7, 11, 13, 17}); // pass a list of values to print()
列表初始化语法对于STL容器和自定义类作用很大(尤其是一些测试代码),但对于数组等类型就没必要强制使用了。总的来说,这是一个能在部分场景下大大提高效率的值得推广的特性。
相关链接:https://zh.cppreference.com/w/cpp/language/list_initialization
2 类内初始化
2.1 内置类型
int i{0};
int i = {0};
int i = 0;
int i(0);
float f{3.6};
float f = {3.6};
float f = 3.6;
float f(3.6);
char chArr[] = {`c`, `h`, `a`, `r`};
char chArr[]{`c`, `h`, `a`, `r`};
char* c = new char{`g`};
char* c = new char(`g`);
2.2 数组
char chArr[]{`c`, `h`, `a`, `r`};
char chArr[] = {`c`, `h`, `a`, `r`};
2.3 STL标准模板库
std::vector<int> v = {1, 2, 3};
std::vector<int> v{1, 2, 3};
std::pair<int, std::string> p = {1, "one"};
2.4 函数
2.4.1 函数参数
大括号表达式做实参传入时,会构造一个initializer_list<int>
对象。
#include <initializer_list>
#include <iostream>
void DisplayInt(const std::initializer_list<int>& ivec)
{
for (auto i : ivec) {
std::cout << i << std::endl;
}
}
int main()
{
DisplayInt({1, 2, 3, 4, 5, 6, 7, 8, 9});
return 0;
}
2.4.2 函数的返回值
2. 5 自定义的类
在C++03中对类的成员变量初始化有两种方式:
- 构造函数初始化列表
- 构造函数内部赋值
一般前者效率会更高。
在C++11中为了避免当内部成员变量较多时,初始化列表显得冗长,开始支持在成员变量中声明时,直接对其进行赋值操作或者初始化列表。
class Test {
public:
Test(){}
private:
int value = 0;
std::string name {"Test"};
};
其执行的顺序为:
- 直接赋值操作
- 初始化列表
- 构造函数内部初始化
其三者可以同时使用,不冲突。
注意:C++11 中不支持在类内部用小括号进行直接赋值操作。