std::vector

読み:エスティーディー・ベクター
外語:std::vector 英語
品詞:名詞

標準C++ライブラリのうちSTLに含まれる、ベクター要素を扱うためのクラス配列と同様の機能を提供する。

目次

mallocnewと同様、配列の連続要素に相当する領域をヒープに確保する。領域は動的に確保され、自動的に解放をしてくれる。

クラスは、ベクター要素に対するアクセスの他、追加や削除といった処理を提供する。

#include <vector>

利点

mallocやnewと違い自動的に開放されるため、メモリーリークが起こらない。

メモリーの連続性

C++ Standard Library Defect Report Listの第69項として、std::vectorのメモリー連続性について触れられている。

69. Must elements of a vector be contiguous?

Discussion:

The issue is this: Must the elements of a vector be in contiguous memory?

Proposed resolution:

Add the following text to the end of 23.3.6 [vector], paragraph 1.

The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().

簡単に訳すと、次のようになる。

69. ベクター要素は連続している必要があるか?

議論:

問題はこれです: ベクター要素は、連続したメモリー内に存在する必要があるか?

決議案:

23.3.6 [ベクター] 第1項の末尾に、次の文を追加する。

ベクター要素は、vがvector<T, Allocator>で、何らかの型Tがbool以外の場合、0 <= n < v.size()の全てにおいて等式&v[n] == &v[0] + nに従うことを意味し、連続的に格納される。

これによれば、「現在の」std::vectorにはメモリーの連続性はあると解釈できる。古い実装では連続していないかもしれないが、そのような古すぎる実装は無視するならば、連続性を理由にmallocやnewなどを使う理由はもはや無い。

必要なだけstd::vectorでメモリーを確保すれば、それは&v[0]から連続したメモリー領域として扱うことができる。メモリーリークに怯える必要は、もはや無いのである。

処理時間

ベクター要素へのアクセスと要素の追加は、定数時間(大きさに限らず常に一定時間)で完了する。

特定の値の検出、ベクターへの要素挿入は、線形時間(入力の大きさに比例する時間)を要する。

ブール型のvector

ビット値であるboolのvector、つまりvector<bool>は、標準C++ライブラリでは特殊化して処理している。

複数のビットがパックして処理されることもあり(処理系依存)、メモリー効率がよいこともある。

vector<bool>は、ビットを反転するメソッドとしてflip();が追加され、また演算子=がbool値を参照するようにオーバーロードされる。

コンストラクター

文法は次の通り。

vector();

vector(size_type size);

vector(size_type num, const TYPE &val);

vector(const vector &from);

vector(input_iterator start, input_iterator end);

上から順に、次のようにベクターは作られる。

  • 引数なし ‐ 空のベクターを作る
  • size ‐ 大きさsizeのベクターを作る
  • numと&val ‐ num個のvalの複製をベクターに入れる
  • &from ‐ fromと同じ内容のベクターを作る
  • startとend ‐ startからendまでの要素を持ったベクターを作る

演算子

文法は次の通り。

v1 == v2

v1 != v2

v1 <= v2

v1 >= v2

v1 < v2

v1 > v2

v[]

各ベクターは、比較演算子によって比較できる。

各ベクターの個々の要素は[]演算子によって調べられる。先頭へのポインターが必要なら&v[0]で求められるが、C++11では、この目的のために新たにdata()というメソッドが追加された。

メソッド

assign()ベクターに要素を割り当てる
at()指定した位置の要素を返す
back()最終要素への参照を返す
begin()先頭を指すイテレーターを返す
capacity()ベクターが保持できる要素数を返す
clear()全ての要素を削除する
empty()ベクターが空ならtrueを返す
end()末尾の次を指すイテレーターを返す
erase()要素を削除する
flip()ビットを反転する (vector<bool>のみ)
front()先頭要素への参照を返す
get_allocator()ベクターのアロケーターを返す
insert()要素をベクターに挿入する
max_size()ベクターが保持できる最大要素数を返す
pop_back()最終要素を削除する
push_back()ベクターの末尾に要素を追加する
rbegin()ベクター末尾を指すリバースイテレーターを返す
rend()ベクター先頭を指すリバースイテレーターを返す
reserve()ベクターが保持できる要素数を設定する
resize()ベクターのサイズを変更する
size()ベクター中の要素数を返す
swap()二つのベクターを入れ替える

C++で、オプション文字列をUTF-8のstring型として扱う方法。

♥や♨といった、シフトJISで表わせないものをファイル名としてオプションに渡す場合はUnicodeとしてオプションを受け取る必要があるが、Windows標準のUTF-16、つまりwchar_tでは処理が面倒なだけで何の利点もない。

そこで、普段はUTF-8にして内部で持ち回し、必要な時には再びUTF-16にしてAPIを呼べばよいのである。

CHogeAppクラスのアプリケーションと想定して説明する。

#include <vector>
#include <string>

上の他に、必要なヘッダーファイルは逐一includeする(<windows.h>など)。

#ifdef _MSC_VER
int wmain(int argc, wchar_t *argv[])
{
    std::vector<std::string> args(argc);
    for (int idx = 0; idx < argc; ++idx)
    {
        int nLen = WideCharToMultiByte(CP_UTF8, 0, argv[idx], wcslen(argv[idx]), NULL, 0, NULL, NULL);
        std::vector<char> buf(nLen + 1);
        nLen = WideCharToMultiByte(CP_UTF8, 0, argv[idx], wcslen(argv[idx]), &buf[0], nLen, NULL, NULL);
        args[idx] = &buf[0];
    }
    CHogeApp theApp(argc, args);
    return (int)0;
}
#else
int main(const int argc, const char *argv[])
{
     std::vector<std::string> args(argc);
     for (int idx = 0; idx < argc; ++idx)
     {
         args[idx] = argv[idx];
     }
     CHogeApp theApp(argc, args);
     return EXIT_SUCCESS;
}
#endif

まず必要なmain関数は上記の通りである。Windowsではwmain関数でUTF-16形式のオプション文字列が得られる。UNIX(BSDやLinux等)はいい加減なので、UTF-8環境であればそのままUTF-8の文字列がchar *で得られるため、それをそのままstd::stringに代入する。

CHogeApp::CHogeApp(const int argc, const std::vector<std::string> &args)
{
    Main(argc, args);
}
CHogeApp::~CHogeApp()
{
}

コンストラクターとデストラクターは必要に応じて内容を書き換える。主処理はCHogeApp::Mainとする。

void CHogeApp::Main(const int argc, const std::vector<std::string> &args)
{
...
}

Main関数以降に必要な処理を書けばよい。この時点で、argcの他に、std::string型の引数が得られている。

std::vectorなので、手動でのメモリー解放は不要。また、参照はargs[0]のように、char *型の時と変わらない。先頭アドレスが欲しいときは&args[idx][0]のようにする。

用語の所属
C++
標準C++ライブラリ
STL
std
関連する用語
クラス

コメントなどを投稿するフォームは、日本語対応時のみ表示されます


KisoDic通信用語の基礎知識検索システム WDIC Explorer Version 7.04a (27-May-2022)
Search System : Copyright © Mirai corporation
Dictionary : Copyright © WDIC Creators club