名前空間
変種
操作

std::vector<T,Allocator>::reserve

From cppreference.com
< cpp‎ | コンテナ‎ | vector
 
 
 
 
void reserve( size_type new_cap );
(C++20 以降 constexpr)

ベクトルの容量(再割り当てなしで保持できる要素の総数)を、new_cap以上になるように増やします。 new_capが現在のcapacity()より大きい場合、新しいストレージが割り当てられます。そうでない場合、関数は何も行いません。

reserve()はベクトルのサイズを変更しません。

new_capcapacity()より大きい場合、すべてのイテレータ(end()イテレータを含む)と要素へのすべての参照が無効になります。それ以外の場合、イテレータや参照は無効になりません。

reserve()の呼び出し後、挿入によってベクトルのサイズがcapacity()の値より大きくなる場合を除き、挿入は再割り当てをトリガーしません。

目次

[編集] パラメータ

new_cap - ベクトルの新しい容量(要素数)
型要件
-
Tは、*thisへのMoveInsertableの要件を満たす必要があります。(C++11以降)

[編集] 戻り値

(なし)

[編集] 例外

  • new_cap > max_size()の場合、std::length_error
  • Allocator::allocate()によってスローされる可能性のある例外(通常はstd::bad_alloc)。

例外がスローされた場合、この関数は効果がありません(強力な例外安全保証)。

Tのムーブコンストラクタがnoexceptではなく、かつTが*thisへのCopyInsertableでない場合、vectorは例外をスローするムーブコンストラクタを使用します。これが例外をスローした場合、保証は無効になり、効果は未定義になります。

(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 TMoveInsertableである必要はありませんでした。 必要

[編集] 関連情報

現在確保されているストレージに保持できる要素数を返す
(public member function) [編集]
可能な最大要素数を返す
(public メンバ関数) [編集]
格納されている要素の数を変更する
(公開メンバ関数) [編集]
未使用のメモリを解放してメモリ使用量を削減する
(公開メンバ関数) [編集]
English 日本語 中文(简体) 中文(繁體)