C++Primer読書ノート5(容器)


容器のいくつかの補遺について
1:コンテナ内の要素タイプの制約
(1)要素タイプは賦値演算をサポートしなければならない.
(2)要素タイプのオブジェクトはコピーできる必要があります.
リファレンスはコンテナの要素として使用できません.リファレンスは一般的な意味での付与演算をサポートしていないので、ここで詳しく説明します.
int m = 1;
int n  = 2;
int &ref1 = m;
int &ref2 = n;
ref1 = ref2;

参照は本質的にconstタイプのポインタであり、ポインタは参照される変数のアドレスを指し、以下に示す.
int m = 1;
int n  = 2;
int *const pref1 = &m;
int *const pref2 = &n;
*pref1 = *pref2; 

したがって、参照間の付与は、参照が指すオブジェクトに対する付与にすぎないが、この「ポインタ」を参照するアドレスは依然として変更されていない(依然としてその間で指す変数のアドレスである)ため、参照を付与しても参照が指すアドレスは変更されない.したがって、参照は一般的な意味での付与演算をサポートしません.
2:容器の要素が容器の場合
C++Primerで述べたように、vector、最後の>>にはスペースを残さなければならないが、vs 2010でテストしても、スペースを残さずに問題はない.
3:反復器について
反復器がサポートする汎用演算
*iter;
++iter;
iter++;
--iter;
iter--;
iter == iter2;
iter1 != iter2;
vector,dequeに対しては、これらのコンテナが連続的に格納されているため、演算をサポートする追加の演算があります.
iter +n ;
iter -n;
iter1 - iter2;
iter1 > iter2;
iter1 < iter2;
iter1 >= iter2;
ite1 <= iter2;
C++primerではiter 1+=iter 2もサポートされています.iter1 -= iter2;これは間違っていて、ポインタの間でこのような演算はできません.
反復器の範囲は左閉右開、すなわちbegin()は最初の要素を指し、end()は最後の要素の後ろの位置を指す.
コンテナ内の要素を変更すると、反復器が無効になる可能性があることに注意してください.
4:コンテナに要素を追加
先頭、末尾、中間の位置の3つの追加方法があります.すべてのシーケンスコンテナでpush_がサポートされていますback、list、dequeはpush_をサポートfront.Insertについて注意しなければならないのは:
insert(iter,t);
insert(iter,n,t);
insert(iter,b,e);

挿入は、もちろん挿入前、つまりiterの前です.
5:コンテナから要素を削除する
先頭、末尾、中間の位置、3つの削除方法があります.
con.erase(p);
con.erase(b,e);
要素を削除し、削除された要素の後ろを指す反復器を返し、pが最後の要素を指す場合、最後の要素の後ろを指す反復器を返します.
範囲の要素を削除し、削除された要素セグメントの後ろの要素の反復器を返します.eがend()を指す場合、反復器も最後の要素の後ろの位置を指します.
6:コンテナ要素へのアクセス
front,backなどを使用して、vectorやdequeなどのメモリに連続的に格納された要素、c[n],c.at(n)操作にアクセスできます.
7:コンテナ要素の変更
変更とアクセスは密接に関連しており、もちろん上記の方法に加えて、コンテナの要素を反復器で変更することもできます.それ以外にもswap(),assign()という2つの重要な関数があります.
swap()は2つのコンテナの内容を交換し、assign()はコンテナの元の要素を削除してから再コピーします.
8:容器の比較
コンテナは、コンテナタイプが同じであることを前提として、コンテナの要素タイプも同じである必要があります.コンテナの比較は各要素の比較に基づいており、これは文字列の比較と類似しており、C++は2つのコンテナのみが要素タイプ定義の関係演算をサポートすることに注意してください.
9:コンテナサイズ:
con.size();
con.max_size();
con.empty();
con.resize();
con.capacity();
con.reserve();

10:pair
pairもテンプレートです.pairオブジェクトの作成方法は次のとおりです.
pair<T1,T2> p1;
pair<T1,T2> p1(v1,v2);
make_pair(v1,v2);
pairは、mapなどの関連コンテナに要素を追加するために主に使用される.
11:mapオブジェクトへのアクセス
mapには、mmap[keyname]=1などの関連タイプにアクセスできるプライマリ・キーとプライマリ・キーの関連タイプがあります.これによりアクセスが容易になるが,mapにこのプライマリ・キーがなければmapにこのプライマリ・キーを挿入し,プライマリ・キーに関連付けられた要素を付与するという弊害もある.
mapコンテナを挿入する場合、プライマリキーが既に存在する場合に挿入に失敗し、pairタイプを返す、pairの最初の要素は既存の要素を指すiterであり、2番目の要素はboolタイプである、例えばpair:iterator,bool>.
12:multimap、およびmultisetに注意すべき事項.
まず両方とも同じプライマリ・キーを持つ要素を挿入でき、multimapでプライマリ・キーが同じであれば、プライマリ・キーに関連付けられた要素は同じでも異なってもよく、関連要素をソートしません.
次にアクセスする場合、multiコンテナには重複するキー値があるため、アクセスする際にはそれほど便利ではなく、以下のような方法があります.
(1)findはcountを結合し、findは最初に出現したiterを返し、countは同じキー値の数を返し、同じキー値要素は連続的に格納されるので、
multimap<int,string>::iterator iter;
iter = mmap.find(xx);
int count cnt = mmap.count(xx);
for (int i=0;i!=cnt;i++,iter++)
{
    cout<<iter->second;
}
(2)lower_bound(),upper_bound()が結合する.
そのうちlower_band(k)は、キー値がkより小さくない最初の要素を指すiterを返す.upper_bound(k)は、キー値がkより大きい最初の要素を指すiterを返します.
multimap<int,string>::iterator iter1,iter2;
iter1 = mmap.lower_bound(xx);
iter2 = mmap.upper_bound(xx);
for(;iter1!iter2;iter++)
{
   cout<<iter1->second<<endl;
}
(3)equal_range()関数
equal_range(k)関数は、ペアiterを格納するpairオブジェクトを返します.この値が存在する場合、pairの最初のiterは一致する最初の要素を指し、2番目のiterは一致する最後の要素の次の位置を指します.
typedef multimap<int,string>::iterator mter;
pair<mter,mter> pp = mmap.equal_range(k);
for(;pp.first!=pp.second;pp.first++;)
{
   cout<<pp.first->second<<endl;
}