MSVCRT std::vector 新しいページはコチラ
提供: yonewiki
(→メンバ関数) |
(→メンバ関数 data) |
||
1行: | 1行: | ||
[[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る | [[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る | ||
== '''概要''' == | == '''概要''' == | ||
− | + | vectorは配列のようなものを扱うのに必要な機能を含んでいます。テンプレート名に指定した型を順序立てて保持し、先頭から後尾までを順番に取り出したり要素数を調べたり、途中の情報から一方向に抜きだしたりといった操作ができます。テンプレートに複数の要素を含む型を指定した場合は多次元配列のようにも振る舞い。PHPやPerlで言うハッシュ配列というモノに近い感じです。数値の型をテンプレート名に与えると、要素同士の比較もできます。vectorのようにあらゆる型のデータを格納できる型になるものをコンテナと読んでいますがここではあまりコンテナという呼び方はしないようにします。コンテナという単語がの意味が貨物船にのせるあの大きな箱をイメージしてしまう人が多いように思います。ここでのコンテナは内包するという意味でどちらかと言うとキッチン道具を入れたりする仕切り箱くらいのもので、その中にきちんといくつかの任意の型の変数を格納するようなイメージなのです。あのでっかい船のコンテナだとなんでも詰め込めそうで汎用性が恐ろしく高いように勘違いするのかな? | |
− | + | はなしはもどって、以下のように定義して使います。 | |
− | <span style = "background:linear-gradient(transparent 75%, #ffbf7f 75%); font-weight:bold; ">std::vector<クラス・構造体・型テンプレート名> 変数名;</span> | + | <span style = "background:linear-gradient(transparent 75%, #ffbf7f 75%); font-weight:bold; "><span style="color:deeppink;">std::vector</span><<span style="color:deeppink;">クラス・構造体・型テンプレート名</span>> 変数名;</span> |
例 | 例 | ||
− | <span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; ">std::vector<QByteArray> objVectorQByteArray_UTF8String;</span> | + | <span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">std::vector</span><<span style="color:deeppink;">QByteArray</span>> objVectorQByteArray_UTF8String;</span> |
40行: | 40行: | ||
} | } | ||
</syntaxhighlight2> | </syntaxhighlight2> | ||
− | + | これがVectorの簡単な使い方です。ここまでは配列を使うのと同じような働きですが、メンバ関数で最初に挿入したり、最後に挿入したりすることを実現できています。自分で配列を操作して制御するよりは楽です。要素番号は0から始まります。 | |
− | ==='''メンバ関数'''=== | + | |
+ | 結果としてはobjVectorInt_dataは{10, 20, 40, 80, 100}になっています。 | ||
+ | |||
+ | ==='''公開 Public'''=== | ||
+ | ===='''メンバ関数 data'''==== | ||
vector<TypeTmplate> obj;とした場合 | vector<TypeTmplate> obj;とした場合 | ||
− | * | + | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;"> TypeTemplate*</span> obj.<span style="color:blue;">data</span>() <span style="color:deeppink;">noexcept</span>;</span> |
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">const TypeTemplate*</span> obj.<span style="color:blue;">data</span>() <span style="color:deeppink;">const noexcept</span>;</span> | ||
− | + | TypeTemplateと記載された部分のvectorを生成するときに指定した型で、 vectorに取り込まれた先頭のデータを返します。データが無くても動作しますが、dataがあるかないか分からないパターンが考えられる場合、受け取った側でdataが有ったか無かったかを確認する必要があります。 | |
− | + | ||
+ | 返される値がポインタ型なので、取り込まれたデータが指定した型のポインタ型である場合は受け取る変数は、更にそのポインタである必要があるため、必ず、TypeTempateで指定した型より*が一つ多い型で受け取ることになります。 | ||
+ | |||
+ | |||
+ | このメンバ関数は、noexceptだ!というキーワードの指定がありますが、これは明示的にこの関数は例外をスローしないことを示しています。これもC++11からの比較的新しい技術です。noexcept(関数名)でその関数がnoexceptかどうかを判定したbool値が取得できます。例外を受け取ることはないので、例外処理を構築する必要が無いことを示しています。このような関数は動作も軽くなることを例外のために準備する処理がなく、それでいて、その処理が安定して動作することを示しています。この関数のように、データを返すだけの単純な関数によく指定されるものです。普段から例外処理を記述しまくっている人でなければ、あんまり気にする必要はないですね。 | ||
+ | |||
+ | ===='''メンバ関数 Insert'''==== | ||
+ | vector<TypeTmplate> obj;とした場合 | ||
+ | |||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">Iterator</span> obj.<span style="color:blue;">Insert</span>(<span style="color:deeppink;">Iterator</span> position, <span style="color:deeppink;">const TypeTemplate&&</span> data);</span> //上記のサンプルプログラムで使った引数の多重定義パターン | ||
+ | |||
+ | ※なんかややこしい型名になっていますが、vector型で扱う他の関数も含めて、配列の位置情報を返す型はIteratorという型名になっています。独自の型名定義にすることで、間違った引数を受け取らないようになっています。数値を受け取るはずなので、内部では単純にInt型のようなものと同じように扱われている筈です。TypeTemplateと書いた部分はよく見るリファレンスなんかでは単に T と表記されるものです。TypeTemplateは型名です。上記のサンプルプログラムではIntで定義されている部分です。const int なので、直接数字を入れれば、const intの扱いになる感じです。Tあらゆる型に対応するためのTemplateというモノです。char** でもいいし、float、longなんでも来いや!なのです。因みに&&は[[Cpp 右辺値参照]]です。右辺値参照の説明はリンク先にあります。サンプルプログラムの10は右辺値なのでね。そして、この関数自体も戻り値は Iterator になっています。 | ||
+ | |||
+ | 全部分からなくても良いですが、他にも同じことをするために様々なパターンで引数を設定できて、多重定義になっています。 | ||
<syntaxhighlight2 lang="cpp"> | <syntaxhighlight2 lang="cpp"> | ||
+ | iterator obj.insert( iterator position, const TypeTemplate& data); | ||
+ | iterator obj.insert(const_iterator position, const TypeTemplate& data); | ||
+ | void obj.insert( iterator position, size_type size, const TypeTemplate& data); | ||
+ | iterator obj.insert(const_iterator position, size_type n, const TypeTemplate& data); | ||
+ | iterator obj.insert(const_iterator position, initializer_list<TypeTmplate> Initializer_listTypeTemlate_obj); | ||
+ | |||
+ | |||
+ | template <class InputIterator>//を使う場合 | ||
+ | void obj.insert( iterator position, InputIterator first, InputIterator last); | ||
+ | iterator obj.insert(const_iterator position, InputIterator first, InputIterator last); | ||
</syntaxhighlight2> | </syntaxhighlight2> | ||
+ | Iteretor を戻り値にもつ関数は挿入した後に、挿入したものが指し示された要素番号が返ってきます。難しい表記が多い世の中だけど、よくよく見るとあらゆる人間が理解できるほど単純なのだ。恐れるべからず。 | ||
+ | |||
+ | |||
+ | |||
+ | ==== '''メンバ関数 assign''' ==== | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.assign</span>(<span style="color:deeppink;">size_type</span> n, <span style="color:deeppink;">const TypeTemplate&</span> u);</span> | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.assign</span>(<span style="color:deeppink;">InputIterator</span> first, <span style="color:deeppink;">InputIterator</span> last);</span> | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.assign</span>(<span style="color:deeppink;">Initializer_list<TypeTemplate></span>);</span> | ||
+ | |||
+ | |||
+ | |||
+ | === '''メンバ関数 emplace_back''' === | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.emplace_back</span>(<span style="color:deeppink;">TypeTemplate(vector<TypeTemplate>&&...)</span>);</span> | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">TypeTemplate&(refference_InsertValue)</span> <span style="color:blue;">obj.emplace_back</span>(<span style="color:deeppink;">TypeTemplate(vector<TypeTemplate>&&...)</span>);</span> | ||
+ | |||
+ | TypeTemplate(vector<TypeTemplate>)はvectorの型テンプレートで型を生成するコンストラクタによって初期化形式である必要があります。?何を言っているの? | ||
+ | |||
+ | 例えばvectorはvector<std::string> obj;のようにstd::string型を定義した場合。objはsdt::string型が順序を持って連続するような値になります。そうすると以下の例のように定義します。 | ||
+ | |||
+ | sample.cpp | ||
+ | <syntaxhighlight2 lang="cpp"> | ||
+ | #include<cstidio> | ||
+ | #include<vector> | ||
+ | |||
+ | int main(int iArgc char** cArgv){ | ||
+ | std::vector<std::string> objVectorStdString_data; | ||
+ | |||
+ | obj.emplace_back(std::string("Hello! VectorDataString!")); | ||
+ | //std::stringのコンストラクタでstd::string型そのものが右辺値参照として引数になる。 | ||
+ | } | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | ※C++17以降は2つ目に書いたように TypeTemplate& のような挿入したデータへの参照を返却され、受け取ることができます。 | ||
+ | |||
+ | ※似た動作をする関数にpush_backという関数があります。emplace_backでは完全転送という処理が行われるためコンストラクタの呼び出しが少なく、処理速度が向上するという利点があります。push_backでは、値を渡したときにコンストラクタがそのあとvector型に格納するときもコンストラクタが呼ばれる仕組みになっています。そしてムーブ処理や値のコピーの処理が発生します。一方emplace_backは右辺値を渡した場合、コンストラクタが呼ばれてそのままvector型に取り込まれます。渡す値が右辺値でない場合は、計算量は同じになります。大量のTypeTemplate型のコンストラクタの引数に合致するデータでコンストラクタの処理が複雑の場合にvector型に格納するときには、良いと思います。大量ですよ。大量。最初の1回の処理には時間がかかるので、大量にvector型を使って、小さなオブジェクトを大量に作る場合もemplace_pushがいいみたい。じゃpush_backって利点がないんじゃ?ふむ、自分もそう思います。 | ||
+ | |||
+ | |||
+ | |||
+ | ==== '''メンバ関数 push_back''' ==== | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.push_back</span>(<span style="color:deeppink;">const TypeTemplate&</span> typeObjValue);</span> | ||
+ | *<span style = "background:linear-gradient(transparent 75%, #cab8d9 75%); font-weight:bold; "><span style="color:deeppink;">void</span> <span style="color:blue;">obj.push_back</span>(<span style="color:deeppink;">TypeTemplate&&</span> typeObjValue);</span> | ||
+ | |||
+ | TypeTemplateはVector<>の<>の中に記述された型名です。 | ||
+ | |||
+ | 例えばvector<std::string> obj;のようにstd::string型を定義した場合。objはsdt::string型の値になっている必要があります。そうすると以下の例のように定義します。 | ||
+ | |||
+ | sample.cpp | ||
+ | <syntaxhighlight2 lang="cpp"> | ||
+ | #include<cstidio> | ||
+ | #include<vector> | ||
+ | |||
+ | int main(int iArgc char** cArgv){ | ||
+ | std::vector<std::string> objVectorStdString_data; | ||
+ | std::vector<std::string> obj; | ||
+ | objVectorStdString_data.emplase_back(std::string("Hello! VectorDataString!")); | ||
+ | //std::stringのコンストラクタでstd::string型そのものが右辺値参照として引数になる。 | ||
+ | for(std::string objStdString_arg: objVectorStdString_data){ | ||
+ | obj.push_back(objStdString_arg.data()) | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | 範囲に基づくfor文を利用して、Vector<std::string>型のstd::string型の値をひとつづつを取り出しています。分からない人は[[Cpp 範囲に基づく for文]]の記事を参照して下さい。C++言語版のforeachと同様の機能がC++11から追加されたことについての記事になっています。 | ||
+ | |||
+ | ※似た動作をするものとしてemplace_backがありますが、emplace_backの方が動作的には速いです。速い理由は[[MSVCRT std::vector#メンバ関数 emplace_back|emplace_back]]の説明の方に記載しています。敷き詰めれば、使う利点は少ないです。 | ||
+ | |||
[[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る | [[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る |