vectorで確保した領域の切り詰め(swap技法)
http://www.geocities.jp/ky_webid/cpp/library/002.html
既に確保した領域を減らしたい場合どうすればよいのかというお話。
reserve関数で領域の確保ができるので、これで減らすことができるか確認してみます。
なお、
vector の容量については、「現在、実際に使っている分」と「とりあえず一括で確保してある分」という2つの見方があることを理解しておくべきです。前者は size() で、後者は capacity() で取得できます。両者の差分が「要素を追加しても、領域の拡張が起こらない個数」ということになります。
ということなのでcapacity関数を使えば、現在確保してある分のサイズを取得できるのでこれで確認してみます。
#include <iostream> #include <vector> using namespace std; int main () { vector<int> array; array.reserve(1000); // 1000と表示 cout << array.capacity() << endl; // 100に切り詰め? array.reserve(100); // 1000と表示 cout << array.capacity() << endl; return 0; }
$ main 1000 1000
だめですね、確保された領域自体は減っていません。
ではどうすれば切り詰めることができるのか?
swap技法というものを使います。
#include <iostream> #include <vector> using namespace std; int main () { vector<int> array; array.reserve(1000); // 1000と表示 cout << array.capacity() << endl; { vector<int> temp(100); array.swap(temp); } // 100と表示 cout << array.capacity() << endl; return 0; }
$ main 1000 100
うまくいってますね。
ただしあくまでもswapは入れ替えなので中身のデータも入れ替わってしまうので実質元のデータの中身はクリアされることになります。
これでは結局新しく変数宣言してるのと変わらないですよね。
そこで中身のデータは残したまま領域の切りつめを方法として名前のないオブジェクトを利用するという方法があります。
#include <iostream> #include <vector> using namespace std; int main () { vector<int> array; array.reserve(1000); // 100まで要素を使う for(int i=0;i<100;++i) { array.push_back(i); } // 1000と表示 cout << array.capacity() << endl; { // 名前のないオブジェクトのコンストラクタにarrayを渡す vector<int> (array).swap(array); } // 100と表示 cout << array.capacity() << endl; return 0; }
これで中身のデータを保持しつつ切りつめができました。
ちなみにこの名前のないオブジェクトについてはまだよくわかってないのでまた調べる必要がありますね。