1 名前:858 [2007/12/24(月) 03:41:59 ] C++標準ライブラリの一つ、STLについて。 前スレ 【C++】STL(Standard Template Library)相談室 7 pc11.2ch.net/test/read.cgi/tech/1185986999/ 過去ログ・リンク・書籍紹介は >>2 以降
730 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 18:04:09 ] TMPとSTLって全然ちがくね?
731 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 18:10:33 ] どっちかっつーと、非 STL 部分の方が TMP っぽいな。 char_traits とか。
732 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 20:53:06 ] iterator_traits
733 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 22:54:48 ] numeric_limits
734 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 22:55:47 ] std::advanceもTMPっていっていいの?
735 名前:デフォルトの名無しさん mailto:sage [2008/02/16(土) 23:00:21 ] いいんじゃね?
736 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 13:45:21 ] vectorやdequeってさ、変更せず読み込みだけなら複数スレッドからアクセスしても 大丈夫ですか?
737 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 13:49:27 ] volatileつけとけ
738 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 14:49:07 ] 誰も書かないならvolatileいらない
739 名前:デフォルトの名無しさん mailto:sage [2008/02/17(日) 15:05:58 ] 例えばVisual C++ならここに書いてある。ほかは知らないけど。 msdn2.microsoft.com/ja-jp/library/c9ceah3b (VS.80).aspx
740 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 14:53:30 ] MFCやVCLにある、StringOfChar って無いですか? ある文字を指定個数分返してくれるメソッド。
741 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 15:08:12 ] string s(10, 'A');
742 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 15:09:32 ] thx! >>741 あやうくfor文で回すところですた。
743 名前:デフォルトの名無しさん [2008/02/18(月) 18:28:13 ] >>731 STLの中でメタプログラミングの要素があるのは iterator_traitsとiterator_tagを使ったディスパッチくらいかな。
744 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 18:33:37 ] >>743 関数テンプレートのオーバーロードを利用した ランダムアクセスとその他の振り分けか。 でもほとんど使ったことないなあ。
745 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 19:36:19 ] Vectorで、5番目の要素の次にデータを挿入したいときは、どう書きますか?
746 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 19:43:45 ] 直接は使わなくても、advance とかで間接的には使ってる事ない?
747 名前:745 mailto:sage [2008/02/18(月) 19:44:02 ] 既存の要素が4の場合と5の場合と、場合分けして、記述する必要があるのでしょうか?
748 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 19:46:41 ] 既存の要素が1とかの時どうすんの?
749 名前:デフォルトの名無しさん mailto:sage [2008/02/18(月) 20:07:40 ] >>745 std::vector なら v.insert(v.begin() + 5, value); とかかな。要素数が最低5個は存在してないとマズイから。 v.size()で要素数調べる必要はあるか。 >>746 そういう意味では使うこともあるなあ。 本では読んだけど自分で書いたことはないな。
750 名前:745 mailto:sage [2008/02/19(火) 08:35:45 ] >v.begin() + 5 あ、イテレーターって足し算できるんですね。 勉強になりました。
751 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 11:13:44 ] vectorのイテレータはランダムアクセス可能だからな。
752 名前:745 mailto:sage [2008/02/19(火) 11:15:48 ] では、vectorのイテレータだけが、+−演算子定義されてるってことですか? (dequeは無理と)
753 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 11:35:47 ] dequeもランダムアクセスイテレータなので+ - は定義されているよ
754 名前:745 mailto:sage [2008/02/19(火) 11:42:15 ] え”〜、自分vectorのみ使ってるのに、それじゃvectorはやっぱり要らない子じゃん。
755 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 11:46:41 ] +や-ができないのは、たとえばlistとかsetの双方向イテレータ。 こいつらでは、インクリメントやデクリメントを繰り返す必要がある。 そんなときはstd::advanceなんていう関数が既に用意されている、もちろんO(N)。 vectorは、要素のメモリアドレスの連続が保障されているので、 組込の配列やmallocなんかで確保したメモリと同じように使えるという点が決定的にほかと違う。 例えばC用のAPIに渡すバッファなんかにも使える。
756 名前:745 mailto:sage [2008/02/19(火) 11:53:08 ] >vectorは、要素のメモリアドレスの連続が保障されているので、 その通りなんですが、上レス読むと、やっぱふつーはイテレーター使えって逝われてるじゃん。
757 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:00:24 ] >>745-750 std::vector<int> v; if (v.begin() + 5 > v.end()) v.resize(5); を実行したら、VS2008 では Debug Assertion Failed! で落ちた。 v.end() を越えるような vector::itrator::opearator+() の結果に対して、 _SCL_SECURE_VALIDATE_RANGEマクロが範囲外を検出して例外を起こしている。 言いたいことはわかるが、融通利かせてほしい。
758 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:03:22 ] じゃ malloc的な使い方する時は、あえて vector<int>って直書きしないとちょっと恐いな。
759 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:05:37 ] >>756 そうだから、vectorで要素へのポインタを使うのはchar*な引数に渡すなんて使い方くらいだね。
760 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:06:05 ] すまん、char*に限らず任意のT*でいいんだ。
761 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:13:51 ] >>757 組み込み配列だって要素数超える足し算は未定義動作なんだぜ。 assert() が 入ってる分ありがたいぐらいだ。
762 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 12:32:11 ] イテレータについて質問です。 イテレータをインクリメントするコストはコンテナによって違うと思うのですが、 STL解説サイトなどで、そのことについて触れているのをみかけません。 速度を知りたければ、実装毎にテストして計るしかないのでしょうか?
763 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:08:30 ] >>762 実際の速度(具体的な処理時間)を知りたいのならそれでいいんじゃね? ソースやアセンブル結果を見て見当をつけても良いけど。
764 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:08:44 ] VC++2005で、 std::map<std::string,int> mp; mp["key000"]=0; とすると、「stringに>演算子がない」ってエラーが出るんだが、これって標準C++準拠の正しいエラーなのかな? それともVC++2005のstringの方がおかしいのかな? ネットで検索した時に普通にstd::stringをキーにしてるソースあったんで、問題ない書き方だとは思うんだが。
765 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:13:37 ] >>762 折角ソースがあるんだから読めばいいんじゃね?
766 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:18:50 ] >>764 標準準拠である確信は無いけど、g++-4.2.3では普通に使えた
767 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:31:04 ] >>764 VS2005でその二行を今書いているコードにペーストしてビルドしたけど、普通に通ったよ。
768 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:32:00 ] >>764 エラーメッセージを変に略さずに、そのまま晒したり Google に放り込むと、 なにか余計なことをしているのが見つかるかもしれない。
769 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:38:22 ] ヘッダincludeしてない時に出るメッセージに似てる…
770 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 13:38:42 ] >>764 ヘッダのincludeが足りてないのでは? #include "stdafx.h" #include <map> #include <string> ←これをコメントアウトすると、「stringに>演算子がない」ってエラーが出る int _tmain(int argc, _TCHAR* argv[]) { std::map<std::string,int> mp; mp["key000"]=0; return 0; }
771 名前:764 mailto:sage [2008/02/19(火) 13:45:41 ] 早いレスd。 #include <string>が抜けてただけでした。 お騒がせして申し訳ないです。
772 名前:762 mailto:sage [2008/02/19(火) 14:07:09 ] >>763 ,765 どうもです。 ソース見て見当つけるの難しいですね(if文のコストとポインタ代入のコストの比率がどのぐらいになるのかとかさっぱりです)。 c++の制御文や演算のコストについて、本などでほとんど目にしないのですが、皆さんはどうやって勉強されました?
773 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 14:20:26 ] >>772 環境によって違うんだから、ある程度一般化せざるをえない本なんかで「勉強」するのは 無理だろ。 速度が要るプログラム組むときに、いろんなコードに対応するアセンブリを見て経験的に 身に付けるのがいいんじゃね? 環境が変われば結果が変わるということにも気をつけないといけない。
774 名前:762 mailto:sage [2008/02/19(火) 14:47:14 ] >>773 なるほど。 経験的に身につけていくしかないですか。 速度見積もるのに技術がいる上、環境で変わることを考えると、 速度はあまり気にせず、プロファイリングしてからボトルネックとなっている部分だけ考えるのがいいんでしょうね。
775 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 14:55:08 ] ばかすぎる
776 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 15:00:48 ] 自己卑下ですか?
777 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 16:31:26 ] スパコンやx86-64のSSE2最適化の場合はvectorを使って、ベクトル化させたい場所はポインタに変換してる。 iteratorなんか使うと最適化してくれないし。
778 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 16:34:19 ] >>772 まあ、こういう細かい部分を気にするのは悪いことじゃないよね。 でもそれはC++の勉強ではなくて、ターゲット環境のしくみを先に勉強した方が良いよ。 CPUがC++で作ったコードをどう処理するのか、とかさ。 昔みたいにクロック数を数えれば分かるような簡単な時代じゃないけど、 その疑問に答えるためには、結局そのあたりの知識が必要だから。
779 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 17:38:29 ] スパコンでどんなソフト作ってんの?
780 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 17:59:00 ] >>777 やっぱり、本物の数値演算には valarray は使い物になりませんか?
781 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 18:00:28 ] 下手にC++で書くよりMatlabで書いた方が早い
782 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 19:57:54 ] >>774 理論的な計算量のオーダーだけは気にしておいた方がいい。 O(N^2)の処理をやっている場所やO(N)の処理を繰り返す場所があったら 適切なコンテナやアルゴリズムを選定することを考えるべき。 結果的にはmapやsetを使うよりvectorを毎回検索、ソートした方が 速いというケースはあるけど、チューニングする以前のエイヤッと決める段階では、 理論的に速いアルゴリズムを選んでおいた方が無難。
783 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 21:41:57 ] >>780 つーか、C++自体が使い物にならなったりする。 ヌパコン屋はFortranしか本気でコンパイラを使ってない。
784 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 21:42:40 ] >>783 ×使ってない ○作ってない
785 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 21:45:54 ] スパコンは並列化がキモだから、 並列化コンパイラの作りやすい Fortran を作りたがるのかもね。 言語仕様も単純で作りやすいし。
786 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 22:00:50 ] 質問です。 vectorのイテレータが有効なイテレータかどうか調べる方法を教えてください。
787 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 22:04:23 ] 質問です。 ポインタが有効なポインタかどうか調べる方法を教えてください。 と同じく、ありません。
788 名前:785 mailto:sage [2008/02/19(火) 22:30:42 ] >>787 わかりました。 ありがとうございます。
789 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 22:34:26 ] 有効なポインタの全てと等しくならなければ有効・・・かも。 大小比較演算子使えるなら簡単になる。 当然、親となる配列が固定されていないと無理だが。 でも、こういうことしていいのかは微妙。 有効に見えるけど、指してる所が違うとかありうるし。
790 名前:786 mailto:sage [2008/02/19(火) 22:40:03 ] vec.begin() < itr && itr < vec.end() こんな感じでやっていたのですがこれでいいのか不安でした。
791 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 22:42:01 ] やるなら vec.begin() <= itr かと。 それで一応どこか有効な要素は指してるかもしれないが、 「元々指していた箇所から決して動いていない」 ということまでは保証してくれない。
792 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 23:00:47 ] 非常に厳密に言えば>>790 のコードは全く意味がない そのコードを実行してよい事前条件が、まさに itr が有効なイテレータであることなので
793 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 23:43:39 ] >>790 reallocateされた場合どうすんのよ?
794 名前:デフォルトの名無しさん mailto:sage [2008/02/19(火) 23:55:31 ] なんだかんだいっても、あれだよあれ。
795 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 00:12:26 ] メジャーリーグに興味持ち始めた頃、STL vs ATLってのがあって何かと思ったら セントルイス・カージナルス対アトランタ・ブレーブスだった。
796 名前:デフォルトの名無しさん [2008/02/20(水) 09:16:18 ] >vectorのイテレータが有効なイテレータかどうか調べる方法を教えてください。 >vec.begin() < itr && itr < vec.end() 自分もこれに関する情報欲しい。 良い記述があれば教えてキボン!
797 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 09:26:21 ] しかしイテレータをそんな長く持ってるのって プログラムを考え直した方がよいような
798 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 09:35:17 ] いや、長く持つんじゃなくて、取得した直後に調べたいんだけど。
799 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 09:36:58 ] *itr で対象をproxyにしてis_valid()でも持たせたら?
800 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 09:44:22 ] そのis_validの実装をどうするかの話をしてるんだろ…
801 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 10:16:45 ] 盛り上がってきますたw
802 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 10:25:13 ] >>798 本当に「取得した直後」なら、i != vec.end()でいいのでは。
803 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 10:35:54 ] サンクス>>802 絶対あってる?保障してくれる?
804 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:09:57 ] >>803 どんな手段で取得した直後を想定しているの?
805 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:10:48 ] どれだけ力強く保証したって、しょせん名無しのレスだぜ。
806 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:12:20 ] こんなに調べる気ゼロな奴だと知ってたら、大嘘教えたのにな。
807 名前:803 mailto:sage [2008/02/20(水) 11:14:32 ] >>804 >>745- のような使い方です。
808 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:16:06 ] >>806 本人からすると、ここで質問することだって調べる気でしょ。 そういう破壊的なことするのは良くないお( ^ω^)
809 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:20:42 ] 答になってないぞ。 >>745 に書いてあるのは「取得したあとにやりたいこと」。 質問は「どんな手段で取得した直後を想定しているのか」だ。
810 名前:803 mailto:sage [2008/02/20(水) 11:30:31 ] >>809 ですから、 vector::insertするためにはイテレーターが要りますよね? で、item[6] としてイテレーターを取得したときに、そのイテレーターは有効なのか無効なのか、という判定。
811 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:51:08 ] >>810 イテレータを取得する前に検査すべき。 例えば、std::vector<int> foo(5); std::vector<int>::iterator it = foo + 6;の結果は鼻から悪魔。
812 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:54:57 ] >>810 item[6] ではイテレータを取得できないと思うよ item.begin() + 6 のことか? itemの6番目の要素が存在するなら、当然有効だし、 存在しないなら、何が返ってこようかくるまいが item.begin() + 6 を実行した時点でアウト
813 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 11:58:27 ] >>810 よくわからんが、こういうことか? void foo(vector<int>& v, int index) { vector::iterator iter = v.begin() + index; // この iter は有効か判断したい. v.insert(iter, 5); } ならば、こう書けば良い void foo1(vector<int>& v, int index) { if (v.size() < index) v.resize(index); // iterが必ず有効になるように、事前にvectorを拡大する. vector::iterator iter = v.begin() + index; v.insert(iter, 5); } void foo2(vector<int>& v, int index) { if (v.size() < index) throw std::invalid_argument("index が大き杉"); // 範囲外なら例外を投げる. vector::iterator iter = v.begin() + index; v.insert(iter, 5); }
814 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 12:15:16 ] 作った直後で無効なイテレータってあるのか? 作ること自体が違法だったり、作った後に無効になったりするのなら分かるんだが・
815 名前:810 mailto:sage [2008/02/20(水) 12:20:17 ] >>813 やりたいことは、 ある行の後に1行追加したい、 だから、foo1でできるのはできます。 でも、ある行の後に1行追加するメソッドくらい、std::vectorとかが標準で持ってて欲しいと思うお。
816 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 12:33:35 ] >>815 却下だな。 - 勝手に resize() するなら、途中の要素を何で埋めるか指定しないといけない。 - 挿入位置は iterator で指定するのが標準コンテナの流儀なのに、この場合だけ インデックスで指定するのはおかしい。 - vector のメンバにしてもユーザーが実装しても効率などは変わらない。 標準で持っていたほうがいい理由が何も思いつかない。
817 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 12:35:35 ] >>814 作った直後のイテレータは、コンテナの中身を指しているか、end()と等値か、だよな。 だからこっちは「本当に作った直後なら、!= vector.end()との比較でいい」って言ってるのに、 この質問者、「自分の訊きたいこと」と「自分の訊いていること」を一致させられないんだよ。
818 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 12:57:08 ] おまえら頑張ってるが、実行効率も考えろ。 結果的に再取得したほうが良かったりして。
819 名前:786 mailto:sage [2008/02/20(水) 13:51:57 ] いろいろ勘違いしていました。 実際はイテレータじゃなくてただのインデックスでした。 0<=index<vec.size() で十分でした。 イテレータの場合は持ってる間vectorを変更しないようにしています。
820 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 13:53:28 ] エエェェェ
821 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 14:18:16 ] >>819 う゛ーう゛ー
822 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 14:20:36 ] これは酷い釣りだ…
823 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 16:22:14 ] 結論としてイテレーターは役立たずでOk?
824 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 16:30:10 ] list をイテレータなしでというのはちょっと vector にはいらないけどさ
825 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 16:37:03 ] listの返したイテレータが無効になるタイミングって、 list本体が破棄された場合と、イテレータ先がeraseされた 時だけでしょうか?
826 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 16:46:18 ] 元からC++にあった下位概念(ポインタ)が要求するメモリ構造を持っているvectorは、 後から加わった上位概念(イテレータ)を使わずとも、下位概念のやり方で各要素を見ていける、 だから「必須ではない」・・・という意味では、無くてもいいかもね。 実際には、stringやlistがbegin() end()してる中、vectorだけ&vec[0]とか使ってポインタでいじるのは えらく不自然だから、vectorもイテレータで扱ってしまうけれども。
827 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 18:04:53 ] >>825 合ってる(要素を消す関数はerase()以外にもあるけど)。あと標準には list1.splice(list2); するとlist2へのイテレータが全部無効になる、と書いてあるけど、 実際にはほぼ間違いなくlist1への有効なイテレータになる。 これは標準の方が訂正される可能性が高い。
828 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 19:40:59 ] >>827 返答ありがとうございます。 listに要素追加したときイテレータを保存しておいて、 それを別なコンテナでインデックス化するってな使い方を しても大丈夫そうですね。 spliceの >実際にはほぼ間違いなく ってところはちと怖いので、使用は避けときます。
829 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 21:01:56 ] >>827 最新のドラフトだと 「移動した要素を指し続ける」 と書いてあるね。
830 名前:デフォルトの名無しさん mailto:sage [2008/02/20(水) 21:36:58 ] 250. splicing invalidates iterators Section: 23.2.3.4 [list.ops] Status: WP Submitter: Brian Parker Date: 2000-07-14 void splice(iterator position, list<T, Allocator>& x); invalidates all iterators and references to list x. This is unnecessary and defeats an important feature of splice. In fact, the SGI STL guarantees that iterators to x remain valid after splice. WPってWorking Paperってなってるけど一度却下されてるんだよね。 で、最新のドラフトだとC++0xで修正されることは決定? WP The proposed resolution has not been accepted as a Technical Corrigendum, but the full WG21 committee has voted to apply the Defect Report's Proposed Resolution to the working paper.