連結リスト(linked list)もコレクションの一種だが、これは名要素をメモリの別々の場所に
格納し、それらをポインタで連結する。std::listは、要素をリストの先頭にも未尾にも挿入
できる双方向リストだ。先頭に挿入するには、push_frontまたはemplace_front関数を使い、
未尾に挿入するには、push_backまたはemplace_back関数を使う。次のコードは整数の連結
リストを作成し、5個の要素を導入する。
連結リストの要素はメモリ上で応援しないことに注意しょう。双方向リストの利点として、リストの先頭でも未尾でも、挿入
の演算はO(1)である。もしリスト内の要素へのポインタを持っていれば、その要素の前また後ろに挿入する演算もO(1)となる。
だが、連結リストの欠点として、リストのn番目の要素にアクセスする演算は、O(n)である、このため、
std::listの実装は、配列の添え字によるインデックス参照を許可しない。
効率 : 連結リストか、配列か?
コレクションに含まれる要素の数が少なければ(64バイト未満)、ほとんど常に配列のほうが
連結リストよりも効率がよい。これはCPUがメモリにアクセスする方法に関係する。
メモリにから値を読むのはCPUにとって遅い処理なので、メモリから1個の値を読む必要がある時、
CPUは、その近傍のインデックスで要素にアクセスすると、その隣のインデックスにある要素もキャッシュに入る
けれども、連結リストの要素は連続していないので、要素の1つをロードする時、無関係なメモリ
がキャッシュに入ってしまう。したがって、コレクション全体をループ処理するような演算では、
配列のほうが連結リストよりも、ずっと効率がよい(時間複雑性は、どちらも O(n)だが)。
「some memo about push and emplace」
Push
push takes an existing element, and appends a copy of it to the container.
Simple, straightforward. push always takes exactly one argument,
the element to copy to the container.
Emplace
emplace creates another instance of the class in the container,
that's already appended to the container.
The arguments to emplace are forwarded as arguments to the container's class's constructor.
Emplace can have either one argument, more than one argument, or no argument at all,
if the class has a default constructor.