しるふぃずむ

どうもプログラマです。好きなものはC#とジンギスカンです。嫌いなものはJava。プログラムおもちろいね。

Initializer lists

「初期化リスト」.
Ideone.com - YEX9jh - Online C++0x Compiler & Debugging Tool
目玉機能の一つであろう,初期化リスト.
Uniform Initializationの一環だと思うのですが,clangやgccのステータスには無いんですよね.
これに含めているんでしょうか.
Uniform Initializationについてはまた別に書くことにして,この記事ではInitializer_listについてのみを.


C++C言語における集成体/aggregate*1の初期化構文を引き継いでいます.

// aggregate type
struct Foo
{
	int i;
	char c;
};

	int arr[3] = { 0, 1, 2 };
	Foo foo = { 0, 'a' };

これにより変数の集合*2を初期化することができます.
しかし,集成体は制限が厳しいため,ユーザ定義クラスではほぼこの記法を用いることができません.

例えばstd::vectorは「可変長配列」なので,配列のように扱いたいものです.
しかしもちろんstd::vector集成体ではないため{}では初期化を行えず,後からメンバ関数で追加していくしかありませんでした.

	std::vector<int> v(0);
	v.reserve(3);
	v.push_back(0);
	v.push_back(1);
	v.push_back(2);

そこで,C++11ではstd::initializer_listが追加されました.
std::initializer_listはで大雑把にこのように定義されています.

template <class T>
class initializer_list
{
public:
	T const* begin() const;
	T const* end() const;
	size_t size() const;
};

値を取りだす為には,constSTLコンテナと同様に扱えば良いので割愛します.

// disaggregate type
struct Bar
{
private:
	size_t d;

public:
	// initializer-list constructor
	Bar(std::initializer_list<int> initr)
		: d{ initr.size() }
	{}
	...
};

	Bar bar = { 1, 2, 3 };

同じ型のオブジェクトを並べ{}で括るとその型のinitializer_listが生成されます.
それを受け取る関数(特にコンストラクタ)を用意することで
非集成体でも集成体に近い記述での初期化を実現できます.

ライブラリも改定されているので,対応しているある程度新しいものであれば
STLコンテナ等もこのように初期化できるようになりました.

	std::vector<int> const u = { 1, 2, 3 };

今までは構築して返すヘルパ関数を用意する等しなければconst宣言できなかったものが
スマートに記述できるようになったのも大きいように思います.

*1:配列型,もしくは構造体(C++では[private/protectedメンバ,ユーザ定義コンストラクタ,基底クラス,仮想メンバ関数,非静的メンバの初期化子]を持っていないクラス(struct, union含む) )

*2:曖昧な言い方ですが.