はじめに
C++の std::vector は、要素が追加される際に、効率化のために実際の要素数よりも少し多めにメモリを確保します。これにより、push_back のたびにメモリ確保が走るのを防ぎ、パフォーマンスを向上させています。
vectorが現在保持している要素の数を size()、確保しているメモリ領域に収容可能な要素の数を capacity() と呼びます。通常、capacity() は size() 以上の値になります。
しかし、要素を大量に追加した後に多数の要素を削除した場合など、capacity() が size() を大幅に上回り、メモリの無駄が生じることがあります。この確保済みの余分なメモリを解放し、capacity() を size() と同じ値まで切り詰めるのが .shrink_to_fit() メソッドです。
【前提】C++11とは?
C++11(シーピープラスいちいち)は、2011年に正式化されたC++言語のメジャーアップデート版です。.shrink_to_fit() はこのC++11で導入された機能のため、利用するにはC++11以降に対応したコンパイラが必要です。
shrink_to_fit() を使ったサンプルコード
このコードは、vector に大量の要素を追加した後、その capacity() がどのように拡張されるかを確認し、.shrink_to_fit() を呼び出して、その capacity() が実際に縮小される様子を示します。
完成コード
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> numbers;
// 1. 大量の要素を追加
cout << "1000個の要素を追加します..." << endl;
for (int i = 0; i < 1000; ++i) {
numbers.push_back(i);
}
cout << "--- shrink_to_fit() 呼び出し前 ---" << endl;
cout << "要素数 (size): " << numbers.size() << endl;
cout << "確保メモリ(capacity): " << numbers.capacity() << endl; // size() 以上の値が表示される
// 2. shrink_to_fit()を呼び出し、メモリの縮小をリクエスト
numbers.shrink_to_fit();
cout << "\n--- shrink_to_fit() 呼び出し後 ---" << endl;
cout << "要素数 (size): " << numbers.size() << endl;
cout << "確保メモリ(capacity): " << numbers.capacity() << endl; // size() と同じ値になる
return 0;
}
実行結果(環境によりcapacityの値は異なります)
1000個の要素を追加します...
--- shrink_to_fit() 呼び出し前 ---
要素数 (size): 1000
確保メモリ(capacity): 1024
--- shrink_to_fit() 呼び出し後 ---
要素数 (size): 1000
確保メモリ(capacity): 1000
コードの解説
size() と capacity()
.size():vectorに実際に格納されている要素の数を返します。.capacity():vectorがメモリ再確保なしで格納できる要素の最大数を返します。
push_back を繰り返すと、capacity が足りなくなった時点で、vector はより大きなメモリ領域を新たに確保し、全要素をそこにコピーします。実行結果では、1000個の要素を格納するために、1024個分の領域が確保されていることが分かります。
.shrink_to_fit()
このメソッドを呼び出すと、vector は確保しているメモリ量を、現在の size() と同じになるように縮小しようと試みます。
- リクエスト:
.shrink_to_fit()は、あくまで「縮小してください」というリクエストです。標準では、コンパイラの実装がこのリクエストを無視することも許されていますが、ほとんどの主要な実装では、期待通りに縮小が行われます。 - 対象: このメソッドは、
std::vectorの他にstd::dequeとstd::stringにも存在します。
まとめ
今回は、C++11の .shrink_to_fit() を使って、vector の余分なメモリを解放する方法を解説しました。
.capacity()は、vectorが確保しているメモリサイズを示す。.shrink_to_fit()を呼び出すことで、.capacity()を.size()と同じ値まで縮小させることができる(可能性がある)。
vector の要素数が最大に達した後、そのサイズが大きく変動しないことが分かっている場合や、メモリ使用量が非常にクリティカルな状況で、このメソッドはメモリ使用量を最適化するための有効な手段となります。
