C++のオマケ的扱いだった1996年頃だったでしょうか。当時のSTLはtemplateが現在ほどには充実/安定していなかったこともあって機能的に貧相でしたが、それでもvectorはこの頃から提供されていました。以来ずっとお世話になってきたvector、改めて"vectorの仕組みとふるまいを観察してみよう"が今回のお題です。目次Page1イケてる実装Page2メモリーの使われ方Page3処理速度イケてる実装vectorは可変長配列、内包する要素数の増加に伴って自動的に要素の格納領域を拡張してくれます。C++の教本を通読した程度のスキルでvectorもどき:novice_vectorをこしらえると、ざっとこんなカンジになりますかしら、至極オーソドックスな実装かと存じます。そのほかモロモロ...};#endifnovice_vectorと本家(?)vectorのふるまいを比べてみます。itemを用意しました。'}';}novice_vector<item>とstd::vector<item>に要素をpush_back()したときのふるまいを観察しましょう。}}fig01......違いますね。要素を格納する領域の確保:reserve(5)したとき、novice_vectorは要素(item)のデフォルト・コンストラクタを5回(対になるデストラクタも5回)呼んでいますが、vectorにはその呼び出しが見当たりません。加えてpush_back()の引数からコンテナ内要素へのコピー時に、vectorは右辺値参照コンストラクトを行っています。12.0のvectorは効率重視のイケてる実装がなされているみたいです。reference)について、少しばかり語っておきましょう。右辺値(R-value)はその名のとおり、代入文の右辺に現れる値です。f(x);においてf(x)が返す値(ただし参照を除く)です。f(x)が返した値がyに代入されたあと、その値はお役御免となりいずれ廃棄される運命です。作った右辺値を捨ててしまうのはもったいない、使えるものは使って時間と空間の無駄を抑えたいシチュエーションで右辺値参照が用いられます。サンプルをお見せしましょう、さきほどのnovice_vector<T>にコピー・コンストラクタを追加します。make_vector()を用意し、その戻り値でnovice_vector<item>をコンストラクトしたときの様子を見てみましょう。}}fig02make_novice(3)が戻り値であるnovice_vector<item>を返して以降、itemのコピーが3回、戻り値の廃棄に伴うデストラクトが3回行われています。C++の最適化オプションによっては、このような挙動となりません。Debugモードで指定されている/Od(最適化なし)での結果です。右辺値参照を引数に取るコンストラクタを追加します。捨てられる運命の右辺値を有効活用しましょう、取り壊し寸前のおうちから家財道具を運び出します。...};fig03ご覧のとおり、右辺値が内包していた3つの要素は格納領域ごと(コピーではなく)移動されたため、右辺値のデストラクトに伴うitemの廃棄が行われていません。右辺値参照をうまく使えば、コンストラクト/デストラクト/コピーのコストが高いオブジェクトに対し、時間の空間の無駄な消費を抑えることができます。C++11ではvectorに限らずほとんどのコンテナで右辺値参照コンストラクタ/コピー演算子が追加されています。それに併せ、vectorにはコスト高な操作に代わるメンバ関数が追加されています。emplace/emplace_backがそれ。"emplace"は配置する/据え付けるといった意味で、insert/push_backが引数に渡された要素をコンテナ内にコピーするのに対し、emplace/emplace_backは要素のコンストラクトに必要な引数をそのまま受け取り、コンテナ内に直接"据え付け"ます。印刷用を表示ブックマークツイート著者プロフィールεπιστημη(エピステーメー)C++に首まで浸かったプログラマ。圧縮・解凍UNIX基本講座@CodeZine『CodeZine(コードジン)』の公式アカウントです。【NEW】デブスト2019デブサミ2019福岡・関西デブサミ2019夏デブスト関西デブサミ2019×ログインEメールパスワード※旧SEメンバーシップ会員の方は、同じ登録情報(Eメール&パスワード)でログインいただけます。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。