std::vector<T,Allocator>::reserve
| void reserve( size_type new_cap ); |
(C++20 以降 constexpr) | |
ベクトルの容量(再割り当てなしで保持できる要素の総数)を、new_cap以上になるように増やします。 new_capが現在のcapacity()より大きい場合、新しいストレージが割り当てられます。そうでない場合、関数は何も行いません。
reserve()はベクトルのサイズを変更しません。
new_capがcapacity()より大きい場合、すべてのイテレータ(end()イテレータを含む)と要素へのすべての参照が無効になります。それ以外の場合、イテレータや参照は無効になりません。
reserve()の呼び出し後、挿入によってベクトルのサイズがcapacity()の値より大きくなる場合を除き、挿入は再割り当てをトリガーしません。
目次 |
[編集] パラメータ
| new_cap | - | ベクトルの新しい容量(要素数) |
| 型要件 | ||
-Tは、*thisへのMoveInsertableの要件を満たす必要があります。(C++11以降) | ||
[編集] 戻り値
(なし)
[編集] 例外
- new_cap > max_size()の場合、std::length_error。
Allocator::allocate()によってスローされる可能性のある例外(通常はstd::bad_alloc)。
例外がスローされた場合、この関数は効果がありません(強力な例外安全保証)。
|
|
(C++11以降) |
[編集] 計算量
コンテナのsize()に対して線形。
[編集] 注釈
reserve()を適切に使用すると、不要な再割り当てを防ぐことができます。しかし、reserve()を不適切に使用すると(例えば、すべてのpush_back()呼び出しの前にそれを呼び出すなど)、実際には再割り当ての回数が増加し(容量が指数関数的ではなく線形に増加するため)、計算量の増加とパフォーマンスの低下を招く可能性があります。例えば、任意のvectorを参照で受け取り、そのvectorに要素を追加する関数は、通常、vectorの使用特性を知らないため、vectorに対してreserve()を呼び出すべきではありません。
範囲を挿入する場合、範囲バージョンのinsert()は、reserve()とその後の多数のpush_back()とは異なり、正しい容量の増加動作を維持するため、一般的に好ましいです。
reserve()はコンテナの容量を減らすために使用することはできません。そのためにはshrink_to_fit()が提供されています。
[編集] 例
#include <cstddef> #include <iostream> #include <new> #include <vector> // minimal C++11 allocator with debug output template<class Tp> struct NAlloc { typedef Tp value_type; NAlloc() = default; template<class T> NAlloc(const NAlloc<T>&) {} Tp* allocate(std::size_t n) { n *= sizeof(Tp); Tp* p = static_cast<Tp*>(::operator new(n)); std::cout << "allocating " << n << " bytes @ " << p << '\n'; return p; } void deallocate(Tp* p, std::size_t n) { std::cout << "deallocating " << n * sizeof *p << " bytes @ " << p << "\n\n"; ::operator delete(p); } }; template<class T, class U> bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; } template<class T, class U> bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; } int main() { constexpr int max_elements = 32; std::cout << "using reserve: \n"; { std::vector<int, NAlloc<int>> v1; v1.reserve(max_elements); // reserves at least max_elements * sizeof(int) bytes for (int n = 0; n < max_elements; ++n) v1.push_back(n); } std::cout << "not using reserve: \n"; { std::vector<int, NAlloc<int>> v1; for (int n = 0; n < max_elements; ++n) { if (v1.size() == v1.capacity()) std::cout << "size() == capacity() == " << v1.size() << '\n'; v1.push_back(n); } } }
実行結果の例
using reserve: allocating 128 bytes @ 0xa6f840 deallocating 128 bytes @ 0xa6f840 not using reserve: size() == capacity() == 0 allocating 4 bytes @ 0xa6f840 size() == capacity() == 1 allocating 8 bytes @ 0xa6f860 deallocating 4 bytes @ 0xa6f840 size() == capacity() == 2 allocating 16 bytes @ 0xa6f840 deallocating 8 bytes @ 0xa6f860 size() == capacity() == 4 allocating 32 bytes @ 0xa6f880 deallocating 16 bytes @ 0xa6f840 size() == capacity() == 8 allocating 64 bytes @ 0xa6f8b0 deallocating 32 bytes @ 0xa6f880 size() == capacity() == 16 allocating 128 bytes @ 0xa6f900 deallocating 64 bytes @ 0xa6f8b0 deallocating 128 bytes @ 0xa6f900
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 329 | C++98 | 挿入が ベクトルのサイズを 直近の reserve()呼び出しで指定されたサイズより大きくする場合、再割り当てが発生する可能性があります。 |
サイズが ベクトルの capacity()より大きくなった場合にのみトリガーされます。 |
| LWG 2033 | C++11 | TはMoveInsertableである必要はありませんでした。 |
必要 |
[編集] 関連情報
| 現在確保されているストレージに保持できる要素数を返す (public member function) | |
| 可能な最大要素数を返す (public メンバ関数) | |
| 格納されている要素の数を変更する (公開メンバ関数) | |
| (DR*) |
未使用のメモリを解放してメモリ使用量を削減する (公開メンバ関数) |