第1回目はこちら↓
ってかこっちのほうが第1回っぽいのは気にしないでください。
STLにはコンテナというテンプレートクラスでできているオブジェクトの入れ物があります。
大きく分けて、シーケンスコンテナ(Sequence Container)、連想コンテナ(Assosiative Container)、コンテナアダプター(Container Adapter)があります。
種類 | 特徴 | 代表的な例 |
---|---|---|
シーケンスコンテナ | 挿入した要素の順序を維持 | vector, deque, list |
連想コンテナ | keyとvalueのペアで管理(ディクショナリとも) | map, multimap, set, multiset |
コンテナアダプター | イテレータをサポートしない | queue, stack |
これらはスレッドセーフではありません。JavaのVectorはスレッドセーフですが……
というかC++とJavaではそもそもスレッドセーフの定義自体ちょっと違うみたいです。
いや、というより使われる文脈が少し違いますね。
Strutsのコーディングはスレッドセーフにとか。
と眠たくなる説明を前半に書いてしまいましたが今日はvector編です。
vectorコンテナで最低限覚えておけばいいことはpush_back()とat()とsize()だけでしょう。
いや、本当はもっと覚えておかないといけないのですが、最初はそれだけで使えるよってことで。
push_back()って最初見たときは変な名前だなーと思いました。
じゃあpush_front()はあんのかい?後ろからだけじゃなくて前からもーみたいななんだかHiwaiな感じですがあります。ただ、vectorコンテナさんはback専門です。
ちなみにpushしたらpullしたくなるじゃなくてpopなんですね。
スタックの用語的な感じです。なので、push_back()とpop_back()がありますが、
vectorコンテナではpop_back()の使い時がいまいち思い浮かびません。
とりあえずひたすらpusu_back()して突っ込んであげてあとは
at()もしくは配列と同じアクセスの方法(operator[]())でアクセスしてあげます。
もちろんイテレータも使えますし、イテレータをつかったときと同等のfor_each()や
Javaの拡張for文と同じものが使えたりします。ちなみにvectorコンテナの中には基本的になんでも入ります。
JavaのようにintじゃなくてIntegerを入れなきゃなんてダサいことにはなってません。
ちなみにArrayListと同じようなC++でのコンテナはvectorです。
ちなみにSTLコンテナはすべてスタック変数として宣言します。
ポインタで宣言してる例は見たことないです。普通の使い方している限りはポインタで宣言するのはあり得ないですが。
まずは伝統的な使い方。
簡単ですね。こんとんじょのいこ。
古いC++ではvectorの初期化方法がないです。アクセスに関しては配列形式のとat()は一緒ですが、
例外を投げるか投げないかの違いです。僕はC++なら別に配列形式でいいんじゃないかなぁと思います。
読みやすいし。JavaでArrayListつかっててget()使うと萎えますもん。
次にもうちょいましな初期化方法+イテレータアクセスです。
イテレータはポインタと同じアクセス方法です。vectorコンテナの中身を現在の順番で今回の場合は前から
順にたどっています。逆から見たいときはreverse_iteratorを使うのですが、
そのときはrbigin(), rend()というのをつかうことになります。
ちなみに、賛否両論あるかと思いますが、イテレータを使ったときだけ++i(前置インクリメント)にしているのは
このあたりの記事が参考になるかと思います。
C++で後置インクリメントよりも前置インクリメントが多用される理由 - 考える人、コードを書く人
Google信者ではありませんが、GoogleのC++コーディング規約でも++iにしろって書いてあった記憶があります。
ちなみにですが、イテレータで使ってるend()は実際の末尾より一つ後ろの要素を返します。
そこにアクセスしちゃだめですよ!
おそらくfor文で書くときに書きやすいようにという配慮でしょう。
C++11で楽に書く方法
C++11便利すぎますね。
ちなみにvectorは自動で倍々ゲームの状態で自動で領域拡張してくれますが、resize()で自分で制御したり、
宣言時にサイズを指定することもできます。調べてみてください。