std::forward_list を試してみます。
ヘッダ <forward_list> で定義 | |
template< class T, class Allocator = std::allocator<T> > class forward_list; |
(1)(c++11以上) |
namespace pmr { template <class T> using forward_list = std::forward_list<T, std::pmr::polymorphic_allocator<T>>; } |
(2)(c++17以上) |
T | - | 要素の型 |
Allocator | - | メモリを確保/解放したり、そのメモリに要素を構築/破棄したりするために使用されるアロケータ。 この型は Allocator の要件を満たさなければなりません。 Allocator::value_type と T が同じでない場合、動作は未定義です。 |
std::forward_list はコンテナ内のあらゆる位置への高速な挿入と削除をサポートするコンテナです。高速なランダムアクセスはサポートされません。このコンテナは片方向連結リストとして実装され、本質的に C で実装された場合と比較していかなるオーバーヘッドもありません。std::listと比較すると、このコンテナは双方向のイテレーションが必要ないため、より空間効率の良い記憶領域を提供します。
リスト内の要素を追加、削除、移動、またはいくつかのリストを横断するそれらの操作は、リスト中の他の要素を現在参照しているイテレータを無効化しません。しかし、(erase_afterを用いて)リストから要素が削除される場合、対応する要素を参照するイテレータや参照は無効化されます。
std::forward_list は(size メンバ関数と operator== の計算量が常に線形時間であることを除いて) Container, AllocatorAwareContainer, SequenceContainer の要件を満たします。
forward_list の各種コンストラクタの例を示します。
コンパイラ : | g++, | 9.3.0 |
OS : | Ubuntu (WSL2), | 20.04 |
[プログラムソース "forword_list_01.cpp"]
#include <forward_list> // forward_list #include <string> // string #include <iostream> // ostream template<typename T> std::ostream& operator<<(std::ostream& os, const std::forward_list<T>& v) { os.put('['); char comma[3] = {'\0', ' ', '\0'}; for (const auto& e : v){ os << comma << e; comma[0] = ','; } return os << ']'; } int main() { // c++11 の初期化リストの構文 std::forward_list<std::string> words1 {"the", "frogurt", "is", "also", "cursed."}; std::cout << "words1: " << words1 << std::endl; // word2 = word1 std::forward_list<std::string> words2(words1.begin(), words1.end()); std::cout << "words2: " << words2 << std::endl; // words3 = words1 std::forward_list<std::string> words3(words1); std::cout << "words3: " << words3 << std::endl; // words4 is {"Mo","Mo", "Mo", "Mo", "Mo"} std::forward_list<std::string> words4(5, "Mo"); std::cout << "words4: " << words4 << std::endl; return EXIT_SUCCESS; }
[出力]
words1: [the, frogurt, is, also, cursed.] words2: [the, frogurt, is, also, cursed.] words3: [the, frogurt, is, also, cursed.] words4: [Mo, Mo, Mo, Mo, Mo]
挿入系のメソッドをいろいろと試してみます。
コンパイラ : | g++, | 9.3.0 |
OS : | Ubuntu (WSL2), | 20.04 |
[プログラムソース "forward_list_02.cpp"]
#include <forward_list> // forward_list #include <string> // string #include <iostream> // ostream template<typename T> std::ostream& operator<<(std::ostream& os, const std::forward_list<T>& v) { os.put('['); char comma[3] = {'\0', ' ', '\0'}; for (const auto& e : v){ os << comma << e; comma[0] = ','; } return os << ']'; } int main(){ // c++11 の初期化リストの構文 std::forward_list<std::string> words1 {"1", "2", "3", "4", "5"}; std::cout << "words1: " << words1 << std::endl; // emplace_front words1.emplace_front("emplace_front"); std::cout << "words1: " << words1 << std::endl; // push_front words1.push_front(std::string("push_front")); std::cout << "words1: " << words1 << std::endl; // emplace_after words1.emplace_after(words1.begin(), "emplace_after"); std::cout << "words1: " << words1 << std::endl; // insert_after words1.insert_after(words1.begin(), std::string("insert_after")); std::cout << "words1: " << words1 << std::endl; // insert_afert & next std::forward_list<std::string> li {"test1", "test2", "test3"}; words1.insert_after(std::next(words1.begin(), 3), li.begin(), li.end()); std::cout << "words1: " << words1 << std::endl; // insert_after & prev // forward_list で prev() を使用することはできません。コンパイルは成功しますが実行時に例外を送出します。 #if 0 std::forward_list<std::string> fi {"test1", "test2", "test3"}; words1.insert_after(std::prev(words1.end(), 3), fi.begin(), fi.end()); std::cout << "words1: " << words1 << std::endl; #endif return EXIT_SUCCESS; }
words1: [1, 2, 3, 4, 5] words1: [emplace_front, 1, 2, 3, 4, 5] words1: [push_front, emplace_front, 1, 2, 3, 4, 5] words1: [push_front, emplace_after, emplace_front, 1, 2, 3, 4, 5] words1: [push_front, insert_after, emplace_after, emplace_front, 1, 2, 3, 4, 5] words1: [push_front, insert_after, emplace_after, emplace_front, test1, test2, test3, 1, 2, 3, 4, 5]
サンプルプログラム ダウンロード
2021-01-03 | - | 新規作成 |