いう、とても古いバージョンのものです。3年ごとに更新されます)。機能強化は強力なものです。古いバージョンを対象にする意味はありません。ベースにした新C++編を始めました。この章の概要この章の概要です。STLコンテナの一種で、双方向連結リスト(アルゴリズムとデータ構造編【データ構造】第4章)を提供します。いう名前の標準ヘッダをインクルードする必要があります。双方向のリストなので、手前の要素へのポインタを保持しており、その分だけメモリ使用量が増加しますし、要素の連結や削除の処理も複雑になります。単方向で構わない場面はわりと多いので、この無駄を省きたいこともあるでしょう。次のように定義されています。クラステンプレート(【言語解説】第20章)なので、使用時にはテンプレート実引数の指定が必要です。動的配列の要素の型です。int型の要素を扱いたいのであれば、以下のようになります。メモリ確保の方法を定義するアロケータと呼ばれるオブジェクトの指定です。デフォルトテンプレート実引数を持っているので省略できます。活用できるので、本章では解説しません。アロケータについては、第32章であらためて取り上げます。違い「容量」という概念はありません。要素が1つ追加されるたびに、新たなメモリが割り当てられます。連結リストですから、連続的な領域を割り当てるわけではありません。「サイズ」の概念は、他のコンテナと同様にあり、単に要素数のことです。sizeメンバ関数を使えば、現在の「サイズ」を取得できます。知りたいときは、emptyメンバ関数を使用できます。emptyメンバ関数を使ってください。sizeメンバ関数は、効率が悪い実装があり得ます。sizeメンバ関数は、実際に連結リストをたどって、要素数をカウントしていく実装も許されていました。そのため、効率が非常に悪い可能性がありました。計算量が保証されるようになりました。max_sizeメンバ関数で取得できます。std::list<T>::size_type型で表現できる最大値になっている環境が多いですが、システムの都合でより小さい値になっている可能性もあります。ここまでに登場したメンバ関数の使用例を挙げます。std::endl;}実行結果10737418235resizeメンバ関数を使うと、サイズを変更できます。現在のサイズよりも大きな値を指定すると、そのサイズになるまで要素を充填します。このとき、要素の型のデフォルトコンストラクタが使用されます。第2引数を指定している場合には、その値を要素の初期化に使用します。現在のサイズよりも小さい値を指定した場合は、指定したサイズになるまで、要素が末尾にあるものから順に取り除かれます。複数のコンストラクタが定義されているので、さまざまな方法でインスタンス化できます。ものと同じ意味合いになっています。方法の場合は、アロケータを渡すデフォルト実引数が隠されています。方法では、要素数を指定して、その個数分の要素を実際に生成しています。場合は、第2引数に指定した値を使って要素を生成し、コピーしています。コンストラクタ周りは強化されています。使用できるようになりました。std::initializer_list}また、ムーブコンストラクタが追加されています。形を除いたすべてで、引数の末尾でアロケータを指定できます。内部で確保した連結リストが破棄されます。継承して使用することは不適切であることに注意してください。連結リストという特性上、ランダムアクセスができません。atメンバ関数のように、要素を直接アクセスする方法は用意されていません。backメンバ関数です。それぞれ、先頭要素の参照、末尾要素の参照を返します。型としては、std::list::reference型になります。空の場合に呼び出した場合は未定義の動作となるので注意してください。要素をアクセスしたいときというのは、先頭から末尾までの各要素を順番にアクセスするという用途が多いです。このような操作には、イテレータを使います。テンプレート実引数が同一であれば、代入演算子を使ってコピーできます。assignメンバ関数を使うこともできます。PrintList(lst);}実行結果333330102030405060708090assignメンバ関数の1つ目の使い方は、第2引数に指定した要素のコピーを、第1引数に指定した個数だけ代入します。2つ目の方は、イテレータを使って範囲を指定し、その範囲内にある要素のコピーを代入します。使えるようになりました。ムーブ代入演算子が追加されています。要素を挿入する方法はいくつかあります。違って、後続の要素をずらす必要性が無いため、コンテナ内の要素を指していたイテレータやポインタが無効化されることはありません。「容量」の概念もないので、再確保&コピーが起こることもありません。この辺りは、連結リストならではの利点でしょう。1つ目の方法として、push_backメンバ関数があります。これは、末尾に要素を追加します。2つ目の方法は、push_frontメンバ関数です。こちらは、先頭に要素を追加します。PrintList(lst);}実行結果43210012343つ目の方法は、insertメンバ関数です。これは、イテレータを使って、任意の位置に要素を挿入します。PrintList(lst);}実行結果333330333339999990101112333339999990使い方が3通りありますが、どれでも第1引数が挿入位置を表しています。挿入位置は、イテレータを使って指定し、そのイテレータが指している位置へ挿入されます。beginメンバ関数で取得したイテレータを指定すれば、先頭要素になるように挿入できます。1つ目の使い方では、第2引数に挿入する値を指定します。この形式の場合は、戻り値で、挿入された値を指すイテレータが返されます。2つ目の使い方では、同じ値を複数個まとめて挿入できます。第2引数が個数、第3引数が挿入する値です。3つ目の使い方では、第2第3の引数で指定した範囲内にある要素を挿入します。これは、別のコンテナや配列からコピーしたい場合に使います。移動による挿入ができるようになっています。push_backメンバ関数が対応しています。lst.push_back(std::move(value));同様に、push_frontメンバ関数が対応しています。lst.push_front(std::move(value));insertメンバ関数の場合は、挿入する要素が1つだけになる形式のみ対応します。外で挿入するオブジェクトを作り、それをコピー(または移動)する必要があります。これは、少なくとも一時オブジェクトを生成するコストが掛かるため(コピーの場合は、さらにコピーのコスト)、使い方によっては非効率さがあります。要素のコンストラクタに渡す引数だけを指定し、メンバ関数内でオブジェクトを作らせるという方法が使えるようになりました。emplaceメンバ関数が対応します。コンストラクタの引数だけ指定し、関数内で生成insertメンバ関数はオーバーロードされていますが、emplaceメンバ関数は1つだけです。insertメンバ関数は、要素の挿入位置を指定する第1引数の型が、std::list<T>::iterator型になっていました。constイテレータで問題ないはずなのに、constイテレータを渡すことができません。std::list<T>::const_iterator型に改められています。「削除」は、コンテナから要素を取り除くということです。行わなければなりません。「削除」はそういった、必要な解放処理までは面倒を見ないことに注意してください。pop_frontメンバ関数があります。前者は末尾にある要素を削除し、後者は先頭にある要素を削除します。PrintList(lst);}実行結果123次に、eraseメンバ関数を使う方法です。PrintList(lst);}実行結果12341eraseメンバ関数の使い方は2通りで、イテレータを1つ渡すか、2つ渡すかの違いです。前者の場合はイテレータが指す要素を削除し、後者の場合は2つのイテレータで作られる範囲内の要素が削除されます。eraseメンバ関数は、削除された要素の次の有効な要素を指すイテレータが返されます。std::advance関数は、イテレータを指定した要素数分だけ進める標準の関数です。std::advance関数を使います。いう名前のヘッダをインクルードする必要があります。std::advance関数のようなイテレータに関する補助関数は、第14章であらためて取り上げます。remove_ifメンバ関数です。前者は指定した値を持った要素をすべて削除し、後者は指定した条件に合う要素をすべて削除します。==演算子で比較した結果が真であれば、その要素を削除します。remove_ifメンバ関数の引数には、関数ポインタや関数オブジェクト(第19章)を渡せます。真を返したとき、その要素を削除します。このような、真偽を表す論理値を返す関数を、叙述関数(プレディケート)と呼びます。動作が異なることに注意が必要です。clearメンバ関数を使うだけです。eraseメンバ関数は、要素の位置を指定するイテレータが、std::list<T>::iterator型になっていました。constイテレータで問題ないはずなのに、constイテレータを渡すことができません。std::list<T>::const_iterator型に改められています。おけるイテレータについて、簡単に紹介します。endメンバ関数で取得できます。rendメンバ関数で取得できます。std::list<T>::const_iterator型です。後者の場合は、イテレータを通して要素を書き換えることができません。std::list<T>::const_reverse_iterator型になります。何であるかは実装依存ですから、ポインタのつもりで扱うことは避けなくてはなりません。提供するイテレータは、ランダムアクセスをサポートしていないためです。イテレータには、このような機能性による分類が規定されています(第14章)。--演算子で1要素分ずつ移動させるか、std::advance関数(第14章)を使用します。いう標準ヘッダをインクルードしてください。なく、他のコンテナのイテレータにも使用できる汎用的な補助関数になっています。各メンバ関数が追加されています。constイテレータを返すものとでオーバーロードされており、constイテレータ型の変数で受け取れば、const版を使えました。auto(【言語解説】第7章)を使いやすくすることが考えられます。要素を整列(ソート)することは非常に簡単に行えるようになっており、sortメンバ関数を呼び出すだけです。<演算子を使って整列を行います。従って、実行結果にあるように、昇順に整列されます。逆に、降順に整列したければ、引数に叙述関数を渡せるバージョンを使用します。これはよく使うものなので、標準で用意されています。>演算子で行うように指示できますから、降順に整列できます。いう標準ヘッダをインクルードする必要があります。関数オブジェクトについては、第19章で取り上げます。いう関数オブジェクトを渡しています。<演算子を使うことを意味しています。sortメンバ関数は、安定なソート(アルゴリズムとデータ構造編【整列】第0章)です。sortメンバ関数の引数には、任意の関数ポインタや関数オブジェクトを渡すことができるので、より複雑な条件で整列を行わせることもできます。次のシグネチャに従う必要があります。std::sort関数(第21章)があります。