可変長配列(VLA)がC++標準に採用されない理由と代替手段「std::vector」の使い方
可変長配列(VLA)とは
可変長配列(Variable Length Array、VLA)とは、実行時にサイズが決まる配列のことです。C99では標準機能として採用されましたが、C++の標準規格には含まれていません。本記事では、その理由と、C++で代わりに利用できる方法を解説します。
可変長配列がC++標準に採用されない理由
スタックは通常、利用できる領域が非常に限られています。そのため、大きなサイズになりうる配列をスタック上に作成しなければならない状況は、プログラムの安定性の観点から好ましくありません。
また、コンパイル時にサイズがわかっているのであれば静的配列を使えばよく、逆にサイズが事前にわからない場合に可変長配列に頼ると、スタックオーバーフローなどのリスクを伴う安全でないコードになりやすくなります。
さらに技術的な理由として、可変長配列をC++にネイティブに組み込むには、型システムに大規模な変更を加える必要があるという点が挙げられます。C++の型システムはテンプレートやオーバーロードといった高度な機能と密接に結びついているため、実行時にしかサイズが確定しない配列型を導入すると、言語仕様全体に大きな影響を及ぼしてしまうのです。
代替手段:std::vector
C++では、可変長配列の代わりとして、標準テンプレートライブラリ(STL)の std::vector を使うのが一般的です。vectorはヒープ領域に要素を格納するため、スタックサイズの制約を受けず、要素の追加・削除も柔軟に行えます。
サンプルコード
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
// ...
// イテレータを使って要素を順に処理する:
for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
cout << *it << endl;
}
return 0;
}出力結果
このプログラムを実行すると、次のような出力が得られます。
1 2 3 4 5
補足:範囲ベースforループを使うとさらに簡潔に
C++11以降では、範囲ベースforループを使うことで、より読みやすく書くこともできます。
for(int x : vec) {
cout << x << endl;
}まとめ
可変長配列がC++標準に含まれないのは、スタック領域の制約や安全性の問題に加え、型システムへの大規模な変更が必要になるためです。実行時にサイズが変わる配列が必要な場合は、STLの std::vector を使うのが安全かつ柔軟なベストプラクティスといえます。
-
C++で解く迷路問題:転がるボールが目的地に止まれるかをBFSで判定する方法
迷路の中にボールがあるとします。迷路には空きスペース(通路)と壁があります。ボールは上下左右のいずれかの方向に転がって空き通路を進むことができますが、壁にぶつかるまで止まりません。ボールが停止したときに、次の方向を選べます。この問題では、ボールの開始位置、目的地、そして迷路そのものが与えられ、「ボールが目的地の位置で停止できるかどうか」を判定する必要があります。迷路は2次元配列で表現され、1は壁、0は空きスペースを意味します。迷路の外周はすべて壁になっています。開始位置と目的地は行・列のインデックス(座標)で与えられます。問題例たとえば、次のような2次元配列で表される迷路を考えてみましょう。0
-
C++で木の特定ノードの部分木に含まれる全ノードのXORを求める方法
問題の概要この問題では、n個のノードからなる木と、木のノードを指定する複数のクエリが与えられます。目的は、指定されたノードを根とする部分木に含まれるすべてのノードの値のXOR(排他的論理和)を求めて出力することです。具体例を使って問題を理解しましょう。次のような木を考えます。クエリ: {1, 6, 5}出力:0 0 5計算過程:1^6^3^2^4^7^5 = 0 6^2^4 = 0 5 = 5ノード1を根とする部分木は木全体に相当し、そのXORは0になります。同様に、ノード6の部分木(ノード6・2・4)のXORも0、ノード5の部分木はノード5のみなのでXORは5となります。解法アプローチこの問