C++11/14學習(四)初始化列表

一. 傳統C++

傳統 C++中,普通數組、沒有構造析構和虛函數的類或結構體都可以使用 {} 進行初始化,也就是我們所說的初始化列表。
而對於類對象的初始化,要麼需要通過拷貝構造、要麼就需要使用 () 進行,不支持{}。

int arr[3] = { 1,2,3 }; // 列表初始化
class Foo
{
private:
	int value;
public:
	Foo(int) {}
};
Foo foo(1); // 普通構造初始化

二. 初始化列表

爲了解決上面的問題,C++11把初始化列表的概念綁定到了類型上,並將其稱之爲 std::initializer_list 。
以下寫法在C++11中都是被允許的:

int static_arr[5] = { 1, 2, 3, 4 };
int static_arr2[]{ 1, 2, 3, 4 }; // 等號要以省略
int* dynamic_arr = new int[5]{ 1, 2, 3, 4 };
vector<int> stl_vec{ 1, 2, 3, 4 };
set<int> stl_set{ 1, 2, 3, 3 };
map<const char*, int> stl_map
{
	{ "Alice", 1 },
	{ "Bob", 2 },
	{ "Cindy", 3 }
};

C++11將初始化列表解釋成一個initializer_list類型的變量(T是列表中元素的類型)。
它相當於一個只讀的容器,只有三個成員函數:size(),begin()和end()。
在上面這個例子中,我們用初始化列表爲STL容器提供初值。
C++11爲STL容器新增了一種構造函數,它可以接收一個initializer_list。

三. 應用

#include <initializer_list> // This header is required
#include <iostream>

using namespace std;

template <class Tp>
void print_ilist(const initializer_list<Tp> &ilist)
{
	for (auto it = ilist.begin(); it != ilist.end(); ++it)
		cout << *it << endl;
}

struct Foo
{
	int vals[10];
	int n = 0;

	Foo(const initializer_list<int> &ilist) {
		for (int v : ilist)
			vals[n++] = v;
	}
};

int main()
{
	initializer_list<int> empty_ilist;
	empty_ilist = { 1, 2, 3, 4 };
	cout << empty_ilist.size() << endl;  // 4

	Foo foo{ 1, 2, 3 };
	Foo bar(empty_ilist);
	cout << "bar.n = " << bar.n << endl; // 4

	initializer_list<float> float_ilist{ 1.0, 1.2, 1.5, 2.0 };
	print_ilist(float_ilist);
	print_ilist({ "Reimu", "Marisa", "Sanae", "Reisen" });
	return 0;
}
發佈了67 篇原創文章 · 獲贊 11 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章