「C ++入門書」の読み方-第03章シーケンシャルコンテナ操作

著者:Ma Zhifeng
リンク:https://zhuanlan.zhihu.com/p/24432568
出典:
著者がほぼ著作権を所有していることを知ってい ます。商用の再版については、著者に連絡して許可を得てください。非商用の再版については、出典を示してください。

ステートメント:

  • 記事の内容は「C ++ Primer Chinese Edition(5th Edition)」から収集・編集されたものであり、著作権は原本に帰属します。
  • オリジナルの本はより詳細で素晴らしい解釈を持っています、学習のために本物の本を購入してください。
  • この記事は学習とコミュニケーションのみを目的としており、いかなる形式の転載も禁止されています

テキスト

  1. 要素を追加
  2. アクセス要素
  3. 要素を削除
  4. コンテナサイズの変更
  5. その他

シーケンシャルコンテナに要素を追加します

  • 押す
    • push_back
    • push_front
  • インサート
  • 好き

ベクトル、文字列、または両端キューに要素を挿入すると、すべてのイテレータ、参照、およびコンテナへのポインタが無効になる場合があります。要素を追加すると、オブジェクトスペース全体が再割り当てされる可能性があるためです(新しい要素が挿入された後、古いスペースではオブジェクトを収容するのに十分ではありません)。オブジェクトのストレージスペースを再割り当てするには、新しいメモリを割り当て、要素を古いスペースから新しいスペースに移動する必要があります。

著者は言う:

追加や削除などのコンテナ操作を使用する場合は、最初に要素スペースのコンテナ割り当ての戦略を検討してください

push_back

コンテナの最後に要素を追加します

arrayとforward_listを除いて、すべてのシーケンシャルコンテナがサポートされています。(覚えておく必要はありません。要素スペースのコンテナー割り当ての戦略を検討してください)

container.push_back(word);

著者は言う:

コンテナをオブジェクトで初期化するとき、またはオブジェクトをコンテナに挿入するとき、実際には、オブジェクト自体ではなく、オブジェクト値のコピーを配置します。また、それはオブジェクトへの参照ではなく、2つの間に接続はありません。

push_front

要素をコンテナヘッドに挿入します

list、forward_list、およびdequeのサポートのみ(覚えておく必要はありません。要素スペースのコンテナー割り当ての戦略を検討してください)

for(size_t ix = 0; ix != 4; ++ix )
{
    ilist.push_front(ix);
}

各要素はコンテナのヘッドに挿入され、最終的には逆の順序になります。
Leetcode整数の逆順を書き換えるなど、この機能を利用できますか?

インサート

任意の位置に0個以上の要素を挿入します

vector、deque、list、stringはすべて
、特別なバージョンのinsertでforward_listをサポートします

挿入には複数のオーバーロードされた関数があります

  • insert(itr、t)itrが指す位置の前にtを挿入します
  • insert(itr、n、t)itrが指す位置の前にntを挿入します
  • insert(itr、itr1、itr2)は、itrが指す位置の前に(itr1、itr2)の範囲の要素を挿入します。
  • insert(itr、il)itrが指す位置の前に{}リストを挿入します

類似性:

  1. 最初のパラメーターはイテレーターであり、挿入位置を指定するために使用されます
  2. 指定されたイテレータが指す位置の前に要素を挿入します
  3. 追加された最初の要素にイテレータを返します

挿入関数には、push_backおよびpush_frontの関数もあります。

list.insert(list.begin(), 1);
list.insert(list.end(), 1);

最初の要素の前に挿入、つまりpush_frontは
最後の要素の挿入されます、つまりpush_back

挿入関数の戻り値を使用する

list<string> lst;
auto iter = lst.begin();
while( cin >> word )
{
    iter = lst.insert( iter, word );
}

常にpush_frontを呼び出すのと同じです

配置する

新しい標準の紹介

プッシュアンドインサートは既製
のオブジェクトを挿入しemplaceはオブジェクトを作成してコンテナに挿入
しますしたがって、そのパラメータはコンテナ要素タイプコンストラクタのパラメータと同じです。

struct Sales_data{
    Sales_data(const string &s, unsigned n, double p);
};

list<Sales_data> c;
c.emplace("934", 25, 1.2);

emplaceを使用する場合は、この違いを覚えておく必要があります。他の例は類推として使用できます。

push_front----emplace_front
push_back----implace_back
insert-----implace

アクセス要素

  • バック
  • 前面
  • 添字

戻り値は、対応する位置要素への参照です。

コンテナの最初と最後にある要素を取得するには、次のことができます。

auto val1 = *c.begin();
auto last = c.end();
auto val2 = *(--last);

より簡単な方法は、前面と背面を使用することです

auto val1 = c.front();
auto val2 = c.back();

使用する前に、コンテナが空かどうかを判断する必要があることに注意してください

下付き文字と比較して、下付き文字が範囲外の場合、atはout_of_range例外をスローします

要素を削除

  • ポップ
    • pop_back
    • pop_front
  • 消去
  • 晴れ

挿入された操作と比較して理解することができます

  • 消去(itr)
  • 消去(itr1、itr2)

消去の戻り値もイテレータであり、最後に削除された要素の後を指します

典型的な例では、リスト内のすべての奇数要素を削除します

list<int> lst = {0,1,2,3,4,5,6,7,8,9};
auto it = lst.begin();
while( it != lst.end() )
{
    if( *it % 2 )
    {
        it = lst.erase(it);
    }
    else
    {
        ++it;
    }
}

forward_list操作

前述のように、最初に要素スペースを割り当てるためのコンテナの戦略を検討してください。forward_listは正確に異なる割り当て戦略のためであり、サポートするには特別な操作が必要です

ele1-->ele2-->ele3-->ele4  
ele1-->ele2--------->ele4

各要素は、要素値を格納するだけでなく、次の要素のアドレスも格納します。
したがって、ele3を削除するには、ele2の後継を変更する必要があり、ele2からele3を取得する方法はありません。

forward_listの要素を追加または削除する操作は、指定された要素の後の要素を変更することによって行われます。

insert_after(p,t)
insert_after(p,n,t)
insert_after(p,b,e)
insert_after(p, il)
erase_after(p)
erase_after(b,e)
implace_after(p,args)

同様に、最後のイテレータはforward_listにとって無意味なので、最初のイテレータが追加されます

before_begin()

コンテナサイズの変更

c.resize(n, t)

コンテナを縮小すると、コンテナの背面にある要素が削除されます。
コンテナを拡大する場合は、tを使用して新しく追加した要素を初期化します。

tはオプションです

イテレータの障害

前述のように、要素を追加または削除すると、イテレータが失敗する可能性があります

コンテナの操作を変更した後、イテレータを再配置することをお勧めします

vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto itr = vi.begin();

while( itr != vi.end() )
{
    if( *itr % 2 )
    {
        itr = vi.insert( itr, *itr );
        itr += 2;
    }
    else
    {
        itr = vi.erase( itr );
    }
}

挿入と消去の戻り値は、ここでイテレータを再配置するために使用されます

また、ループ状態では、事前に取得する代わりにvi.end()が使用されます

auto end = vi.end();
wihle( begin != end ){}

操作の追加と削除後、endも変更されるため、すぐに取得する必要があります

  1. 戻り値を使用してイテレータを再配置します
  2. すぐに終了し、終了値をキャッシュしないでください

おすすめ

転載: blog.csdn.net/qq_26751117/article/details/53730436