1。概要
forward_list は、C++11 によって追加された新しいタイプのコンテナです。その基礎となる実装はリスト コンテナと同じであり、リンク リスト構造も使用します。ただし、forward_list は単一のリンク リストを使用するのに対し、list は二重リンク リストを使用する点が異なります。 。以下に示すように:
上の図では、H はリンク リストのヘッダーを表します。a) は単一リンクリストを表し、b) は二重リンクリストを表します。リンク リストを使用してデータを保存する最大の特徴は、データを一元的に (配列のように) 保存しないこと、つまりリンク リスト内のデータの保存場所が分散していることであることがわかります。ランダムであり、リンクされたリスト全体のデータはポインタを通じて線形関係が維持されます。したがって、forward_list コンテナはリスト コンテナと同じ特性を持ちます。つまり、シーケンス内の任意の位置で要素を挿入または削除することには優れていますが、アクセスに関しては他のコンテナ (配列やベクトルなど) ほど効率的ではありません。保存された要素。
さらに、単一リンクリストは二重リンクリストほど柔軟ではないため、forward_list コンテナの機能はリストコンテナに比べて大幅に制限されます。たとえば、単一リンク リストは前方から後方へのみトラバースでき、逆方向のトラバースをサポートしていないため、forward_list コンテナは前方イテレータのみを提供し、双方向イテレータは提供しません。これは、forward_list コンテナには rbegin()、rend() などのメンバー関数がないことを意味します。
では、forward_list コンテナはリスト コンテナと同じ特性を持ち、リスト コンテナの方がより多くの機能を提供できるのに、なぜ forward_list コンテナが必要なのでしょうか。もちろん、forward_list コンテナの最下層は単一リンク リストを使用しますが、これは役に立たないわけではありません。たとえば、同じタイプの同じ数の要素を格納する場合、単一リンク リストの方が消費するメモリ スペースが少なく、スペース使用率が高く、単一リンク リストで特定の操作を実装する際の効率が高くなります。
リスト コンテナではなく forward_list を選択する主な理由は効率の高さであり、言い換えれば、リスト コンテナと forward_list コンテナの両方で動作を実現できる限り、forward_list コンテナを優先する必要があります。
2. メンバー関数
メンバー関数 | 関数 |
---|---|
before_begin() | コンテナ内の最初の要素の前の位置を指す前方反復子を返します。 |
始める() | コンテナ内の最初の要素の位置を指す前方反復子を返します。 |
終わり() | コンテナ内の最後の要素の後の位置を指す前方反復子を返します。 |
cbefore_begin() | これは before_begin() と同じ機能を持ちますが、 const 属性がその上に追加され、要素の変更には使用できない点が異なります。 |
cbegin() | これは begin() と同じ機能を持ちますが、const 属性がその上に追加され、要素の変更には使用できない点が異なります。 |
いくつか() | これは end() と同じ機能を持ちますが、 const 属性がその上に追加され、要素の変更には使用できない点が異なります。 |
空の() | コンテナ内に要素があるかどうかを判断し、要素がない場合は true を返し、要素がない場合は false を返します。 |
max_size() | コンテナに含めることができる要素の最大数を返します。これは通常、2^32-1 などの大きな値であるため、この関数を使用することはほとんどありません。 |
フロント() | 最初の要素への参照を返します。 |
割当() | コンテナの元のコンテンツを新しい要素に置き換えます。 |
プッシュ_フロント() | コンテナの先頭に要素を挿入します。 |
emplace_front() | コンテナの先頭に要素を生成します。この関数は、push_front() と同じ機能を持ちますが、より効率的です。 |
ポップフロント() | コンテナの先頭にある要素を削除します。 |
emplace_after() | 指定された位置の後に新しい要素を挿入し、新しい要素を指す反復子を返します。insert_after() と同じ関数ですが、より効率的です。 |
挿入後() | 指定された位置の後に新しい要素を挿入し、新しい要素を指す反復子を返します。 |
消去後() | コンテナ内の指定された位置または範囲内のすべての要素を削除します。 |
スワップ() | 2 つのコンテナ内の要素を交換するには、2 つのコンテナに格納されている要素のタイプが同じであることを確認する必要があります。 |
サイズ変更() | 容器のサイズを調整します。 |
クリア() | コンテナに保存されているすべての要素を削除します。 |
splice_after() | ある forward_list コンテナ内の指定された位置または範囲にある要素を、別のコンテナ内の指定された位置の後に挿入します。 |
削除(val) | コンテナ内の val に等しいすべての要素を削除します。 |
削除_if() | 条件を満たすコンテナ内の要素を削除します。 |
個性的() | コンテナ内の隣接する重複要素を削除し、1 つだけ残します。 |
マージ() | 事前に並べ替えられた 2 つの forward_list コンテナをマージすると、マージされた forward_list コンテナは依然として順序どおりです。 |
選別() | コンテナ内の要素の位置を変更して並べ替えます。 |
逆行する() | コンテナ内の要素の順序を逆にします。 |
さらに、C++ 11 標準ライブラリには、forward_list コンテナーに含まれる begin() および end() メンバー関数とは異なる 2 つの関数 begin() および end() も追加されています。操作オブジェクトはコンテナまたは通常の配列のいずれかです。操作オブジェクトがコンテナの場合、コンテナに含まれる begin() および end() メンバ関数と同じ機能を持ちます。操作オブジェクトが通常の配列の場合、begin() 関数は最初の要素へのポインタを返します。同様に、end() は配列の最後の要素の後の位置へのポインタを返します (これは最後の要素ではないことに注意してください)。
forward_list コンテナにはstd::swap(x , y)
非メンバー関数もあります (x と y は同じ型の要素を格納する forward_list コンテナです)。これは swap() メンバー関数とまったく同じ機能を持ちますが、使用構文が異なるだけです。
次の例は、いくつかのメンバー関数の使用法を示しています。
#include <iostream>
#include <forward_list>
using namespace std;
int main()
{
std::forward_list<int> values{1,2,3};
values.emplace_front(4); // {4,1,2,3}
values.emplace_after(values.before_begin(), 5); // {5,4,1,2,3}
values.reverse(); // {3,2,1,4,5}
for (auto it = values.begin(); it != values.end(); ++it) {
cout << *it << " ";
}
return 0;
}
操作の結果は次のようになります。
3 2 1 4 5
forward_list コンテナの使用に関連する関数
size() 関数が forward_list コンテナには提供されていないことはわかっていますが、forward_list コンテナに格納されている要素の数を取得したい場合は、ヘッダー ファイル <iterator> で distance() 関数を使用できます。例えば:
#include <iostream>
#include <forward_list>
#include <iterator>
using namespace std;
int main()
{
std::forward_list<int> my_words{1,2,3,4};
int count = std::distance(std::begin(my_words), std::end(my_words));
cout << count;
return 0;
}
操作の結果は次のようになります。
4
さらに、 forward_list コンテナイテレータの移動には、++
演算子を使用して 1 つのステップで移動するだけでなく、advanced() 関数も使用できます。次に例を示します。
#include <iostream>
#include <forward_list>
using namespace std;
int main()
{
std::forward_list<int> values{1,2,3,4};
auto it = values.begin();
advance(it, 2);
while (it!=values.end())
{
cout << *it << " ";
++it;
}
return 0;
}
操作の結果は次のようになります。
3 4
3. forward_listコンテナの作成
forward_list コンテナは、テンプレート クラス forward_list<T> (T はストレージ要素のタイプ) の形式で <forward_list> ヘッダー ファイルに含まれており、std 名前空間で定義されているためです。したがって、コンテナーを使用する前に、コードに次の 2 行のコードを含める必要があります。
#include <forward_list>
using namespace std;
std 名前空間は、forward_list コンテナを使用するときにも指定できます。
forward_list コンテナを作成するには、大きく 5 つの方法があります。
- 要素を含まない空の forward_list コンテナを作成します。
std::forward_list<int> values;
これは、作成後に要素を追加することもできる forward_list コンテナを作成する一般的な方法です。
- n 個の要素を含む forward_list コンテナを作成します。
std::forward_list<int> values(10);
このようにして値コンテナを作成します。このコンテナには 10 個の要素が含まれており、各要素の値は対応する型のデフォルト値になります (int 型のデフォルト値は 0)。
- n 個の要素を含む forward_list コンテナを作成し、各要素の初期値を指定します。例えば:
std::forward_list<int> values(10, 5);
これにより、それぞれの値が 5 である 10 個の要素を含む値コンテナーが作成されます。
- 既存の forward_list コンテナの場合、このコンテナをコピーすることで新しい forward_list コンテナを作成できます。例えば:
std::forward_list<int> value1(10);
std::forward_list<int> value2(value1);
この方法では、古いコンテナと新しいコンテナに格納されている要素の型が一貫していることを確認する必要があることに注意してください。
- 新しい forward_list コンテナは、他の種類のコンテナ (または通常の配列) の指定された領域の要素をコピーすることで作成できます。例えば:
// 拷贝普通数组,创建forward_list容器
int a[] = { 1,2,3,4,5 };
std::forward_list<int> values(a, a+5);
// 拷贝其它类型的容器,创建forward_list容器
std::array<int, 5> arr{ 11,12,13,14,15 };
std::forward_list<int> values(arr.begin()+2, arr.end()); // 拷贝arr容器中的{13,14,15}