アルゴリズムの勉強をしていて少しつまずいてしまったので自分用にメモ。
C++の vector、特に2次元配列(vector<vector<int>>)の宣言や初期化において、コンパイルエラーや意図しない挙動に悩まされるケースは少なくありません。
本記事では、正しい初期化方法とその仕組みについて解説します。
1. 基本:1次元配列の初期化
vector を宣言し、特定の初期値で埋める場合の基本構文は以下の通りです。
vector<型> 変数名(要素数, 初期値);
✅ 正しい書き方
// サイズ10、すべての要素を 3 で初期化
vector<int> vec(10, 3);
❌ よくある間違い
// × コンパイルエラー:第2引数に型名を書いている
vector<int> vec(10, int 3);
C++において、関数の引数は「値」を渡す場所であり、「型」を宣言する場所ではありません。3 は整数リテラルとして解釈されるため、修飾なしでそのまま記述してください。
2. 本題:2次元配列の初期化DP
(動的計画法)などで使用する N×Nのグリッドを作成し、初期値を設定する場合の記述です。
✅ 正しい書き方
// N行N列、すべて -1 で初期化
vector<vector<int>> dp(N, vector<int>(N, -1));
なぜ vector<int>(N, -1) が必要なのか?
vector のコンストラクタの第2引数は、「新しく作成する要素のコピー元となる値」 を要求します。
2次元配列における「要素」とは、1次元配列(vector)そのものです。 そのため、第2引数において vector<int>(N, -1) と記述し、「初期値として使用する1次元配列のオブジェクト」をその場で生成して渡す必要があります。
追記
vector dp(N,vector(N,-1));
この書き方でも動きます (クラステンプレートのテンプレート引数推論)
例えば3次元配列だと
vector>> dp(N,vector>(N,vector(N,-1)));
を vector dp(N,vector(N,vector(N,-1)));
と書けて楽
3. 注意すべき間違い
以下のコードはコンパイルエラー、または意図しない動作の原因となります。
❌ 初期化のカッコ忘れ
// × エラー:型のみを指定しており、オブジェクトが生成されていない
vector<vector<int>> dp(N, vector<int>);
❌ 型の不一致
// × エラー:vector<int> を期待している場所に int を渡している
vector<vector<int>> dp(N, N);
外側の vector の要素型は vector<int> ですが、整数型の N を渡しているため型エラーとなります。
まとめ
-
vector の初期化引数は (要素数, 初期値)
-
引数に型名(int など)を書かず、直接値を渡す
-
2次元配列の初期化では、第2引数で 「内側の vector を生成して渡す」 記述が必須
vector<vector<int>> dp(N, vector<int>(N, -1));