MSVCRT std::vector 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(メンバ関数 emplace_back)
(メンバ関数 data)
 
1行: 1行:
 
[[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る
 
[[Windows#MSVC Runtimeリファレンス|MSVC Runtimeリファレンス]]に戻る
 
== '''概要''' ==
 
== '''概要''' ==
 vectorは配列のようなものを扱うのに必要な機能を含んでいます。テンプレート名に指定した型を順序立てて保持し、先頭から後尾までを順番に取り出したり要素数を調べたり、途中の情報から一方向に抜きだしたりといった操作ができます。テンプレートに複数の要素を含む型を指定した場合は多次元配列のようにも振る舞い。PHPやPerlで言うハッシュ配列というモノに近い感じです。数値の型をテンプレート名に与えると、要素同士の比較もできます。
+
 vectorは配列のようなものを扱うのに必要な機能を含んでいます。テンプレート名に指定した型を順序立てて保持し、先頭から後尾までを順番に取り出したり要素数を調べたり、途中の情報から一方向に抜きだしたりといった操作ができます。テンプレートに複数の要素を含む型を指定した場合は多次元配列のようにも振る舞い。PHPやPerlで言うハッシュ配列というモノに近い感じです。数値の型をテンプレート名に与えると、要素同士の比較もできます。vectorのようにあらゆる型のデータを格納できる型になるものをコンテナと読んでいますがここではあまりコンテナという呼び方はしないようにします。コンテナという単語がの意味が貨物船にのせるあの大きな箱をイメージしてしまう人が多いように思います。ここでのコンテナは内包するという意味でどちらかと言うとキッチン道具を入れたりする仕切り箱くらいのもので、その中にきちんといくつかの任意の型の変数を格納するようなイメージなのです。あのでっかい船のコンテナだとなんでも詰め込めそうで汎用性が恐ろしく高いように勘違いするのかな?
  
 以下のように定義して使います。
+
 はなしはもどって、以下のように定義して使います。
  
 
 <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%, #ffbf7f 75%); font-weight:bold; "><span style="color:deeppink;">std::vector</span><<span style="color:deeppink;">クラス・構造体・型テンプレート名</span>> 変数名;</span>
45行: 45行:
 
 結果としてはobjVectorInt_dataは{10, 20, 40, 80, 100}になっています。
 
 結果としてはobjVectorInt_dataは{10, 20, 40, 80, 100}になっています。
  
==='''メンバ関数'''===
+
==='''公開 Public'''===
 +
===='''メンバ関数 data'''====
 +
 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;とした場合
 
 vector<TypeTmplate> obj;とした場合
  
69行: 84行:
 
 
 
 
  
=== '''メンバ関数 assign''' ===
+
==== '''メンバ関数 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;">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;">InputIterator</span> first, <span style="color:deeppink;">InputIterator</span> last);</span>
92行: 107行:
 
   std::vector<std::string> objVectorStdString_data;
 
   std::vector<std::string> objVectorStdString_data;
  
   obj.emplase_back(std::string("Hello! VectorDataString!"));  
+
   obj.emplace_back(std::string("Hello! VectorDataString!"));  
 
   //std::stringのコンストラクタでstd::string型そのものが右辺値参照として引数になる。
 
   //std::stringのコンストラクタでstd::string型そのものが右辺値参照として引数になる。
 
}
 
}
 
</syntaxhighlight2>
 
</syntaxhighlight2>
  
※C++17以降は2つ目に書いたように TypeTemplate& のような挿入したデータへの参照を返却され、受け取ることができます。
+
 ※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リファレンス]]に戻る

2021年2月14日 (日) 00:00時点における最新版



個人用ツール
名前空間

変種
操作
案内
ツールボックス