目次
はじめに
C++の標準ライブラリが提供するコンテナ(vector
やmap
など)は、オブジェクト指向の基本に則り、オブジェクトを生成するためのコンストラクタを複数持っています。これにより、プログラマは状況に応じて最適な方法でコンテナを初期化できます。
この記事では、コンテナの種類を大きく3つのグループに分け、それぞれの代表的なオブジェクト構築方法を網羅的に解説します。
- 固定長配列 (
std::array
) - シーケンスコンテナ (
std::vector
など) - 連想コンテナ (
std::set
,std::map
など)
1. std::array
の構築
std::array
は、コンパイル時にサイズが決定される固定長の配列です。
サンプルコード
#include <iostream>
#include <array>
using namespace std;
// arrayの内容を表示するヘルパー関数
void print_array(const string& title, const array<int, 4>& arr) {
cout << title << ": { ";
for (int val : arr) {
cout << val << " ";
}
cout << "}" << endl;
}
int main() {
// (a) 値初期化なし (要素の値は不定)
array<int, 4> a;
// (b) 空の初期化子リスト (全要素が0で初期化)
array<int, 4> b = {};
// (c) 初期化子リストで初期化
array<int, 4> c = {10, 20, 30, 40};
// (d) コピーコンストラクタ
array<int, 4> d = c;
// (e) ムーブコンストラクタ
array<int, 4> temp_e = c;
array<int, 4> e = move(temp_e);
print_array("a (初期化なし)", a);
print_array("b (ゼロ初期化)", b);
print_array("c (値で初期化)", c);
print_array("d (コピー)", d);
print_array("e (ムーブ)", e);
return 0;
}
2. std::vector
等のシーケンスコンテナの構築
std::vector
, std::list
, std::deque
などは、実行時にサイズが変動する動的な配列です。
サンプルコード
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// vectorの内容を表示するヘルパー関数
void print_vector(const string& title, const vector<double>& vec) {
cout << title << ": { ";
for (double val : vec) {
cout << val << " ";
}
cout << "}" << endl;
}
int main() {
// (a) 空のコンテナ
vector<double> a;
// (b) サイズを指定 (要素は0.0で値初期化)
vector<double> b(3);
// (c) サイズと初期値を指定
vector<double> c(4, 9.9);
// (d) 初期化子リストで初期化
vector<double> d = {1.1, 2.2, 3.3};
// (e) コピーコンストラクタ
vector<double> e = c;
// (f) ムーブコンストラクタ
vector<double> temp_f = d;
vector<double> f = move(temp_f);
// (g) 他のコンテナの範囲から初期化
vector<double> g(c.begin(), c.end());
print_vector("a (空)", a);
print_vector("b (サイズ指定)", b);
print_vector("c (サイズと値)", c);
print_vector("d (リスト初期化)", d);
print_vector("e (コピー)", e);
print_vector("f (ムーブ)", f);
print_vector("g (範囲から)", g);
return 0;
}
3. std::set
等の連想コンテナの構築
std::set
, std::map
などは、キーに基づいて要素が自動的にソートされるコンテナです。
サンプルコード
#include <iostream>
#include <set>
#include <string>
using namespace std;
// setの内容を表示するヘルパー関数
void print_set(const string& title, const set<char>& s) {
cout << title << ": { ";
for (char val : s) {
cout << val << " ";
}
cout << "}" << endl;
}
int main() {
// (a) 空のコンテナ
set<char> a;
// (b) 初期化子リストで初期化 (自動でソートされ、重複は除去される)
set<char> b = {'Z', 'X', 'Y', 'Z'};
// (c) コピーコンストラクタ
set<char> c = b;
// (d) ムーブコンストラクタ
set<char> temp_d = b;
set<char> d = move(temp_d);
// (e) 他のコンテナの範囲から初期化
string source_str = "hello";
set<char> e(source_str.begin(), source_str.end());
print_set("a (空)", a);
print_set("b (リスト初期化)", b);
print_set("c (コピー)", c);
print_set("d (ムーブ)", d);
print_set("e (範囲から)", e);
return 0;
}
まとめ
今回は、C++の各種コンテナを構築(生成・初期化)するための様々なコンストラクタのパターンを解説しました。
初期化方法 | array | vector | set /map |
デフォルト(空) | △ (値不定) | ◎ | ◎ |
サイズ指定 | (テンプレート引数) | ◎ | ☓ |
サイズと値で指定 | ☓ | ◎ | ☓ |
初期化子リスト {...} | ◎ | ◎ | ◎ |
コピー/ムーブ | ◎ | ◎ | ◎ |
範囲から | ☓ | ◎ | ◎ |
コンテナの特性と、プログラムの要求に応じて、最適なコンストラクタを選択することが、効率的で読みやすいコードを書くための第一歩となります。