【C++】STL(Standard Template Library)相談室 10
7 :
デフォルトの名無しさん :2008/08/29(金) 00:12:00
早速質問です。 set< set< int > > s; set< set< int > >::iterator i( s.begin() ); i->insert( 12 ); をコンパイルすると、 error: passing 'const std::set<int, std::less<int>, std::allocator<int> >' as 'this' argument of 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, _Alloc>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = int, _Compare = std::less<int>, _Alloc = std::allocator<int>]' discards qualifiers と言われる。 これは何が間違ってる?
ねぇねぇ。
>>4 の書籍紹介にも出てくるSTL標準講座(ハーバーと知るとちょw)なんだけど
これのp.17中段(vectorの代表的なメンバ関数の紹介)に
「end()関数はベクタの最後の要素を指す反復子を返します」
って、書いてあるんだけど、これって間違いだよね?
end()関数は末尾(最後の要素のひとつ後)を指すんだよね?
実際、
vector< int > v( 10, 1 );
vector< int >::const_iterator iter = v.end();
cout << *iter;
みたいにやると、「デリファレンスできねーよ、ばーかばーか」って
実行時エラーがでやがりまくりやがりますりやがりますり。
楽しいか?
うん。
死んだら、end()が最後の要素を指す様になりますか?
いや、お前が終わるだけ。
p.14の 「コンテナ内を巡回するには、 begin() で先頭を指す反復子を取得し、 反復子の値が end() と等しくなるまで反復子をインクリメントします。」 ってのも、実際にプログラムしたらエラーでる。 つか、気になったのは、シルト先生は for ループの条件に不等号を使うんだよね。 for ( int i = 0, i < 10, ++i )みたいに。 これはAccelerated C++ではやるべきじゃないって最初の方で書かれてる。 なぜなら、普遍の表明を正しく立てられなくなるし、エラーも発見しにくくなるから。 ループの終わりは正確に示すべきで、特に理由がなければ for ( int i = 0, i != 10. ++i )のように書く方が良い、と。 こうすれば、ループが [0,10) であることを正しく表明できる。 どっちを信じたらいいんだ。
俺の個人的な嗜好でいうと、不等号のほうが好きだな。 簡単に要素のスキップとかできるし
ランダムアクセスイテレータには < が使えるが、そうでなければ使えない。 != は任意のイテレータで使用可能である。 従って、後でコンテナの種類を入れ替えたりする可能性があるので!= が無難である。 というのが、STLのイテレータに関する結論。 (コンテナの種類を変更するのは、そんな簡単な仕事じゃなかったりするが。。。) for 文の本体でカウンタの値を変更出来るのだから、 終了条件 i != 10 がいつも正しい表明とは限らない。 それが正しい表明なら != で書けば良いだろう。 i < 10 でも十分正しい表明であるケースは起こりうる。 ので、int カウンタに対しては、どちらでも良くて、時に応じて好きな方を選ぶ。 ただ、そんな細かい事より、もっと気を配るべき事は沢山ありそうだが。
>というのが、STLのイテレータに関する結論。 なるほど。納得。
で、結局、.end()はどこを指すのか。
末尾であってるよ。
>>7 エラーメッセージを見る限り、i.operator ->の戻り値の型がconst set<int>になっているみたい。
これが正しいのか規格のsetのあたりみても分からなかった、すまん。
もっと単純な形、例えば以下の2つのコードを考える。 // OK! set< int > s; set< int >::iterator iter; s.insert( 12 ); iter = s.begin(); cout << *iter << endl; // Error! set< int > s; set< int >::iterator iter; iter = s.begin(); cout << *iter << endl; // ここでError イテレータ iter はコンテナ s の冒頭を指しているわけだが コンテナ s が空っぽだから、実際には何も指していない。 何も指していないものはデリファレンスできないのでエラーになる。 当然、存在しないオブジェクトのメソッドも呼び出せない。 なので・・・ set< int > base; base.insert( 0 ); set< set< int > > s; s.insert( base ); set< set< int > >::iterator i; i = s.begin(); i->insert( 12 ); のようにあらかじめなんか突っ込んでおけばOK。
キーなんだから、状態が変わるとコンテナが困った事になるわな。
vectorやmapの要素にvector<double>やvector<float>を混在させたいのですが、 そういうことは出来ないんですかね?
できるお
>>25 どうやってやるですかね?
std::vector<std::vector> vec;
vec.push_back(std::vector<float>);
とかだと、vectorのtemplateの型を1行目で指定してないので、
compileがもちろん出来ないんですが。
指定すればいいんだよ。
>>27 >>26 のvecの第一要素はvector<double>で、
第二要素はvector<float>にしたいという意味です。
boost使っていいなら std::vector<boost::any> とか std::vector<boost::variant<std::vector<double>, std::vector<float> > >
boostすげぇぇぇぇぇぇぇぇぇ!
それほどでもない
>>32 boostさんは謙虚なライブラリで大人気
あまり調子こくとリアルで痛い目を見て病院で栄養食を食べる事になる
boostはすごいと思うぜ? これを知ってるかどうかで生産性が違う
いろんな有名な本でもboost位は紹介されるしな
一部が次期標準に採用されるくらいだしな
progress_displayも次期標準に入るんでしょうか?
期待して待ってて欲しいお(`・ω・´)
progress_displayはC++0xには入りません
vectorで2次元配列を作って、任意の行を基準にソートするにはどうしたらいいすか?
BOOST_FOREACH
ファイル読み込んで、データ整理する際のみソートが1度だけあって それ以降、そのデータへのアクセスは走査のみの場合 vector と list、Dotch?
ランダムアクセスができソートが速いのがvector。 任意の位置への挿入削除が速いのがlist。 よってvectorかと。
STLportで_STLP_SHORT_STRING_SZを変更して使用してる人いる? 値を変更しても安全なんかな。
コンテナを持つクラスで コンストラクタ、デストラクタ内でclearするべき? コンテナ自身、コンストラクタ、デストラクタで clearは保証されてないんですか?
clearしなくていいよ
std::vector<union{int, int*}> hoge; みたいな、要素を共用するようなこと出来ませんか? unionをtypedefしちゃえばいいんだろうけど、 文を短くできないかなぁと思ったんですが…
boost::any
boost::variant
boostがすごすぎて濡れてきた。
52 :
sage :2008/09/20(土) 23:20:38
vector<int> hoge(100); hoge[0]=41;hoge[1]=10;hoge[2]=20;hoge[3]=2;.... となってるときに、hogeからある決められた数字以下の列だけを先頭から順番に 抜き出したいのですが、一行で書けるでしょうか? よろしくお願いします。
std::transform(hoge.begin(), hoge.end(), to.begin(), std::bind2nd(std::less<int>(), n));
copy_ifがあれば簡単なんだが
std::remove_copy_if(hoge.begin(), hoge.end(), std::back_inserter(hage), std::not1(std::bind2nd(std::less<int>(), n))); std::copy_ifでできるよ、と書こうと思ったら無かったorz C++0xマダー
hoge | pstade::oven::filtered(_1 <= boost::lambda::constant(n)); 0xで標準になるかもしれないrange baseの<algorithm>, <numeric>が楽しみですね
Effective STL第43項を参考に,独自のループをfor_eachを使ったものに書き換えています つまり, class Widget { public: void redraw() const; }; list<Widget> lw; for (list<Widget>::iterator i = lw.begin(); i != lw.end(); ++i) { i->redraw(); } 上記のようなメンバ関数を呼び出すようなループを下記のように置き換えています。(Effective STLからそのまま引用) for_each (lw.begin(), lw.end(), mem_fun_ref(&Widget::redraw)); 現在悩んでいる問題は multimap<int, Widget *> widget_map; for (multimap<int, Widget *>::iterator i = widget_map.begin(); i != widget_map.end(); i++) { i->second->redraw(); } このようなmapコンテナに対するループをどうやってfor_eachに置き換えるか…というものです。 for_each (widget_map.begin(), widget_map.end(), .... //これは無理 for_each (widget_map.begin()->second, widget_map.end()->second .... // イテレータでないのでやはり無理 なにか良いアイディアはあるでしょうか?
関数を挟めばいいんだよ。 struct MapRedraw { void operator ()(std::multimap<int, Widget *>::value_type const& e) const { e.second->redraw(); } }; for_each(widget_map.begin(), widget_map.end(), MapRedraw());
59 :
57 :2008/09/23(火) 20:13:42
>>58 なるほど
メンバ関数のみを使うという方法に固執していました
スコット・メイヤーズ宣伝乙
関数がポコポコ出てくるのがウザい
STLを勉強したての頃に抱いた強い期待に比べると、 まったくと言っていいくらい使う機会が無いなぁ、for_eachは。 まぁ、俺はそうだっていう単なるスタイルの話だけれど。
0xで無名関数がかけるようになったら、もうちょっとfor_eachの出番も増えるはず。
0x厨うぜぇ
標準でこれぐらいできるようになって欲しい for_each(widget_map | map_values | indirected , bind(&Widget::redraw, _1));
>>65 最後のindirectedは要らなくないか?
>>65 確かにこの場合だと要らんね、指摘ありがとう
lambda使えないとalgorithmって生きてこないんだよね
std::vectorを走査する時、 添字よりiteratorのが早いんですか?
イテレータがポインタの実装なら、operator[]関数を呼ぶオーバーヘッドの分だけ速いんじゃね。
72 :
デフォルトの名無しさん :2008/09/27(土) 03:05:54
そんなんで変わるほど、コンパイラはへぼじゃない。 判りやすい単純な書き方をするのが一番
それは普通最適化で消える。 ただ、一般的な話をすると vectorはクラス/構造体であり、内部にポインタメンバを持っている。 そのため、[]で参照する時には、必ずメモリ上にベースアドレスを示す変数を読む必要がある。 一方、iteratorはただのポインタであり、レジスタ割付が可能。 そういう意味で、昔の「ポインタ/配列どちらが速い」論争とは意味が違う。 とはいえ、実装と最適化次第なのは当然。
・ i < vec.size() より itor != vec.end() の方が実態を正確に表現している ・ algorithm に渡す時はイテレータ のような理由で、イテレータを使ったほうが、より C++ らしいとはいえるだろう。
またit++が遅いから++itにしろの話か
またC++が遅いから++Cにしろの話か
またC#が遅いからCにしろの話か
79 :
デフォルトの名無しさん :2008/09/28(日) 12:46:14
環境: VisualStudio 2008 find_ifアルゴリズムを使いたいのですが、 書籍やwebページを参照して find_if(v.begin(), v.end(), IsTestes); というふうに記述するとコンパイラがエラーを吐きます。 (IsTestedの行: error C3867: 関数呼び出しには引数リストがありません。 メンバへのポインタを作成するために & を使用してください) &を付けて関数ポインタにしても解決しませんでした。 これはVS2008がヘンなの? 俺が何か見落としてる?
IsTestes側がまずいと思われ 関数オブジェクトでぐぐるべき
>>80 ありがとうございます。
関数オブジェクトに変えたら通りました。
>>73 実装の話だが、VC++のChecked Iterator有効状態だとiteratorアクセスが遅く、
vectorの単なる走査だと生ポインタ取り出してインクリメントしたほうが速くなる
結果というのをどっかで見た
デバッグ版で速度を気にしても仕方がない
>>82 デフォルトで安全なほうに振ってるからな
それ知らずにベンチマークして「遅いwww糞杉www」
って言ってる奴マジ恥ずかしい
サンプルコードに下記のコードがあったのですが解説がないので どのような動きをするのかわかりません・・。 誰か簡単に教えていただけませんか //------------------------------------------------------------ //STLの補助マクロ // // #define foreach(type,obj,i) \ for(type::iterator i=(obj).begin();(i)!=(obj).end();(i)++) #define const_foreach(type,obj,i) \ for(type::const_iterator i=(obj).begin();(i)!=(obj).end();(i)++)
>>85 解説しろといわれてもこまるほど
簡単なというか基本的なことしかでてきてない
コードなんだがなにが分からないの?
イテレータ知らないの?
>>85 typeにはstd::vectorとかのコンテナ型を指定する。objはそのインスタンス。iはイテレータを使ったループ変数だ。
こんな風に使う。
std::vector<int> vecx;
(略).
foreach(std::vector,vecx,i)
{
std::cout<<*i;
}
88 :
デフォルトの名無しさん :2008/10/04(土) 05:58:22
今時のコンピュータ早くて 多少重い部品使っても全然平気。
C++でそんなマクロを作る意味あんの?
マクロじゃないとできへんのや・・
>>85 のマクロだけど
「#define foreach(type,obj,i)」のtypeを無くして引数を2個だけにできますか?
何に使うかはともかくとして、ちょっと気になった。
BOOST_FOREACHもマクロなんですがw
でっていう
VC++なら8からfor eachが使える。
BOOST_FOR_EACHを使うとループを二重にも三重にも出来る std::vector<std::vector<int> > vec(10, std::vector<int>(10)); BOOST_FOREACH(std::vector<int>& row, vec) BOOST_FOREACH(int& i, row) i = 999;
>>97 autoは別スレの話題だ
typeofならギリギリ可
99 :
デフォルトの名無しさん :2008/10/05(日) 15:35:23
vectorへのアクセスを速くする良い方法ってありますか? いま、 for(vec::iterator it=vec.begin();it!=vec.end();it++) access to *it を for(int i=0, int num=vec.size(), Type *ptr=&vec[0];i<num;i++) accsess to ptr[i]; とかやっちゃってます。
>>99 BOOST_FOREACHを使うとend()がキャッシュされる分高速化されるらしい。
endをキャッシュするより
>>99 のように 数値変数でループ回数を制御する方が速いことが多い
x86のような性能優先のCPUならどっちでも変わらないが
組み込みに使える普通のCPUだと差がつくことが多い
102 :
99 :2008/10/05(日) 16:14:17
なるほど、最適化すればx86なら変わらないのですね。ありがとう。 ちなみに、目的としては動的に確保できる多次元配列のアクセスを速く したいんだけれども。array[][][]と同程度の速度が出たりしますか。 ・・・なんて聞いてないで自分で実験してみればいいか^^; BOOSTはデフォルトでビルドできないためソースを人に渡せないから、 速度の関係ないアルゴリズム検証用にしか使ってません。
BOOST_FOREACHはビルドしなくても使える
>>103 そうじゃなくてboost入れてない人がいるって話だろ
105 :
99 :2008/10/05(日) 16:48:34
そうです。使わない人にとっては、BOOST入れるのって結構面倒ですしね。 ソース書いて、アセンブラ見てみたんだけど、一見したところ変わらないみたい。 通常、静的な多次元配列array[a][b][c]ならば、連続で並んでるのが保障 されてるから、一発で目的のアドレスを参照できるから速い。 疑問なのが、動的な多次元配列の場合、 int ***ptr ptr = new int**[a] ptr[i] = new int*[b] ptr[i][j] = new int[c] とした時、 ptr[i][j][k]にアクセスすると、ptr[i]にアクセスして、入ってる番地を見 て、更に入ってる番地を・・ってのを繰り返すけど、メモリアクセスは通常 遅いので、動的配列は遅いのだけど。 で、普通に考えてvectorも同じような多重メモリアクセスをやってるような 気がするんだけど、遅くならないのかな。
vector<vector<vector<int> > >とかなら105のと同じように遅くなるだろと思う。
仕方がない 行毎に列の大きさを変えられる利便性とのトレードオフ
108 :
99 :2008/10/05(日) 17:16:38
うーむ、やっぱそうですよね。ありがとうございます。 僕のケースでは大抵の場合は行毎のサイズは固定で、初期化の時から変化 しないって場合が多いので、1次元配列で確保してます。例えば画像デー タみたいに、ユーザの入力にあわせて初期化サイズが変わるみたいな状況です。 この場合、データの規則性・連続性は保障されるので、構造的には静的多 次元配列と同じパフォーマンスが出せるはずですが、最適化してくれるものですか? もし可能なら、変数沢山のマクロから解放されてソースも読みやすくなるし、 メモリリークもしないから非常に素敵なんだけどな・・・。
長方形や立方体でよければ、1次元に詰め込んでv[i * x + j]とアクセスする方法が取れる。
boost::multi_arrayもあるけどインタフェースが変態的なんだよな 結局の所自分で簡単なクラス作って使うのが無難
111 :
デフォルトの名無しさん :2008/10/15(水) 12:18:18
vectorで配列を作って vectorの要素0から99までの最大値をmax_elementで求める vectorの要素100から199までの最大値をmax_elementで求める vectorの要素200から299までの最大値をmax_elementで求める 省略 という処理をしたいんですが、どのようにすればいいでしょうか?
a = *max_element(&v[0], &v[100]); b = *max_element(&v[100], &v[200]); c = *max_element(&v[200], &v[300]);
省略
114 :
デフォルトの名無しさん :2008/10/15(水) 12:37:38
ありがとうございます。 それで出来るはずだと思って試していたら、他の所でミスしてましたorz。 iteratorを使って ループ文中で if(count%100){ a=*max_element(iterator,ここが分からない); } という風にiteratorを基準に、後ろ100個目までを範囲指定することを出来ませんか?
ランダムアクセスイテレータなら a=*max_element(iterator, iterator + 100);
vectorなんだからランダムアクセスできるでしょ
117 :
デフォルトの名無しさん :2008/10/15(水) 12:53:31
出来ました!ありがとうございます!!
118 :
デフォルトの名無しさん :2008/10/19(日) 00:12:46
疑問なんだけど、vectorの配列から作ったiteratorってのは、 ポインタの配列なの?
最適化の結果ポインタと同じような動作になるけど そのものじゃないはず
実装によるんじゃなかった? 単にポインタをtypedefしている実装もあれば、classにしてる実装もあるって 聞いたような気がする夢をみたかもしれない
vectorの配列から作ったiteratorって言うと、 vector<vector<hoge> >::iterator のことかい。
俺はvector<hoge>[N]のイテレータ、つまりvector<hoge> *のことかと思った でもどっちにしても話が合わない気がする
vi->begin() とか気持ち悪いコード初めて書いたわ
別に普通かな
ハッシュテーブルの辞書みたいなもんだろ。
まったく気持ち悪くないよ
127 :
118 :2008/10/20(月) 09:02:02
>>121 ,122
vector<int>::iteratorみたいなもんです。書き方が悪かったですね。すみません
2Dライブラリだったらピクセルデータの配列を引数
3Dライブラリだったら座標データの配列を引数
にとる関数がありますけど、そういう関数にvectorで管理してるデータを
渡したいときは、どのようにしてますか?
私は、vectorに入ってるデータのサイズ分の配列を作って、そいつに入れてから
ライブラリの関数に渡すってことをしてたんですけど、もっとスマートな方法って
ないですか?
vectorのイテレータがポインタだという保証はない でもvectorの内容がメモリ上で連続している保証はある だからvがvector<T>なら、Tの配列を要求する関数に&v[0]を渡しても大丈夫 イテレータitに対応するポインタを渡したければ&*itのようにすればいい
129 :
デフォルトの名無しさん :2008/10/20(月) 12:26:11
わかりやすい解答ありがとうございます。 vector便利過ぎる
vectorでイテレータなんか使ったこと無いな。 Win32 APIを使う場合は、配列を使わない訳にはいかないから、 何番目という数字が必要な場合が出てくるし、 配列要素アクセスでは、i < vec.size()の記述でないとおかしいから。
>>130 のイテレータバージョンはたぶんこんな感じだな
vectorでインデックスなんか使ったこと無いな。
algorithmを使う場合は、イテレータを使わない訳にはいかないから、
beginとendが必要な場合が出てくるし、
イテレータアクセスでは、i != vec.end()の記述でないとおかしいから。
つか、
>>130 が vector で iterator 使ったことがあるかどうかなんて
地球上の誰も興味のない話を唐突にされても。
内部でやってることは一緒じゃないの
いや、vector のイテレータとか、型が分からないと使えないしめんどいー インデックスでいいじゃんでも C++ 使うならイテレータつかったほうがいいのかなーどうしよー と迷うに迷って混在させてgdgdになってる俺みたいな人には重要な話
C配列との橋渡し的な役目もあるしね。使う人/使わない人がいるのは当然かと。
>>134 対象のvectorが見えてるのに型が判らないってどういう状況だ?
いちいちstd::vector<foo>::iteratorと書くのが面倒だと言っているだけだと思う。 早くautoが欲しい。
どっちも似たようなものだし、いざとなれば相互に変換できるし、どうでもいい
構文糖は重要だよ 各種LL言語が有用性を示してるじゃん
イテレータとポインタは構文糖の関係にはない
141 :
デフォルトの名無しさん :2008/10/22(水) 19:03:29
double型 と char型のメンバを持つ構造体をvectorにいれて、全要素入れ終わったらソートみたいにしてるんですけど、 mapとかつかったらもっと効率よくなりますか?ソートするキーはdouble型の値で、降順です。
143 :
デフォルトの名無しさん :2008/10/22(水) 21:30:53
ファイルからや手からの入力ならset使えば、ソート時間はほぼ無い。 読み込んでいる間にソートされるので。 もしメモリ間の転送であっても速いとは思う
mapじゃなくてpairかもしれません。 pairでdouble型とchar型のメンバを作って、doubleをキーにソートって感じにしたいんですが、どうしたらいいですか? char型のメンバは重複する場合もあります。
扱う要素数によるよ。 整数とかポインタなら、数千まではvectorの方が一般的に他のコンテナよりも速い
つまりvectorにガシガシいれてあとからソートですか?
147 :
デフォルトの名無しさん :2008/10/22(水) 21:50:32
実測しよう
148 :
デフォルトの名無しさん :2008/10/22(水) 21:51:29
それほど速度を気にしないなら、setにぶち込むのが簡単。 いれたらソート終わっているので
そんなに速度は気にしません。あまりにも比較して遅いなら別ですが
気になるなら測れ、としか。
速度気にしてないのか
気にしてないわけではありません。 実測してみます
typedef struct{ double dist; char name[20]; }DIST; int main(){ std::set<DIST> distance; distance.insert( 200 ); →2要素を代入するにはどうすればいいですか? }
>>153 DIST型のオブジェクトを渡すべきところへ200を渡してどーすんですか
あらかじめvectorでサイズを決め打ちするなら早いけど、 領域を増やしていくならsetのほうがはやい
>>154 渡し方がわかりません。ソートに使うキーはdoubleのほうです
こんなんでどう? struct DIST { double dist; char name[20]; DIST(double d, char* str) : dist(d) { std::strcpy(name, str); } friend class Comp; }; struct Comp { bool operator()(const DIST& d1, const DIST& d2) const { return d1.dist < d2.dist; } }; int main() { std::set<DIST, Comp> distance; distance.insert(DIST(200, "abc")); //→2要素を代入するにはどうすればいいですか? distance.insert(DIST(100, "def")); distance.insert(DIST( 50, "ghi")); for (std::set<DIST, Comp>::const_iterator pos = distance.begin(); pos != distance.end(); ++pos) std::cout << pos->dist << ", \"" << pos->name << "\"\n"; }
distance.insert( std::pair(200.0 ,"moziretu") ); こうですか?
>>160 これ頭に付けてるよな
#include <iostream>
#include <cstring>
#include <set>
>>161 コピペみすってました・・・
struct DIST {
double dist;
char name[20];
DIST(double d, char* str) : dist(d) {
std::strcpy(name, str);
}
friend class Comp;
};
struct Comp {
bool operator()(const DIST& d1, const DIST& d2) const {
return d1.dist < d2.dist;
}
};
これがどういうことをしてるのかわかりません。
>>162 まず二要素を一度に代入できるように、DISTにコンストラクタを付けた。
こうする事によって一時オブジェクトが生成できるようになる。
次にソートの基準をdoubleにするために、叙述関数もしくは関数オブジェクト
を書かなければならないが、この場合は関数オブジェクトを書いている。
というのもstd::setのデフォルトの比較基準はless<DIST>となり、これは
存在しないので、自分で書かなければならないからだ。そこで比較関数
オブジェクトにCompを使う事にして自分で書いている。
classがstructになっててなんかおかしいよ
>>164 わかったよこれでいいだろ
class DIST {
double dist;
char name[20];
public:
DIST(double d, char* str) : dist(d) {
std::strcpy(name, str);
}
double getdist() const {
return dist;
}
const char* getname() const {
return name;
}
friend class Comp;
};
struct Comp {
bool operator()(const DIST& d1, const DIST& d2) const {
return d1.dist < d2.dist;
}
};
int main()
{
std::set<DIST, Comp> distance;
distance.insert(DIST(200, "abc")); //→2要素を代入するにはどうすればいいですか?
distance.insert(DIST(100, "def"));
distance.insert(DIST( 50, "ghi"));
for (std::set<DIST, Comp>::const_iterator pos = distance.begin(); pos != distance.end(); ++pos)
std::cout << pos->getdist() << ", \"" << pos->getname() << "\"\n";
}
おまえら暇だな… DIST dist; distance.insert(dist);
func(string hoge){ } という関数に char mozi[256];で宣言された文字列をfunc(mozi)みたいに渡せますか?
ええ
なんでそんなことができるんですか?
stringのコンストラクタにconst char*を取るものがあるから
なるほど!STLってほんとにすごいですね
でもSTL関係ないですね!
stringはSTLだろ basic_string<char>でテンプレートだし。
>>173 const char *を引数にとるコンストラクタを持つ文字列クラスは、STL固有ではありません。
んなこたーない
自前で似たようなモノを作れるのに?
>>176 const T* だよ
>>178 STLであろうがなかろうが全部自前で似たようなものを作れるぞ
なんか話が噛み合ってない
わかってないんだよ、おそらく本当にw
ということにしたいのですね。
はいはい模範回答。 もともとのAlexanderのSTLにはbasic_string<>は無かった。 しかし、標準化の過程でSTLコンテナに適合するようにされた。 basic_string<>がalgorithmと重複するようなメンバ関数を持っていたり、 しかもそれがイテレータではなくsize_typeを扱ったりするのはその名残。
>>173 の
>basic_string<char>でテンプレートだし。
てのが気になるなあ…
「stream I/O もテンプレートだからSTL」とか言い出しかねない勢い。
入念に勉強してない限り、 「C++コンパイラに付いてくるtemplate classを使ったもの全部=STL」 と思っている人は多い気がする 実用上困る事項でもないし・・・
定期的に出る話題だから 今回も「ああ、またですか」てなもんだ。 でもbasic_stringはもう 仲間に入れてあげてもいいと思うんだ。
やだよ basic_stringなんてC++標準化委員会も「失敗作だった」と 認めているじゃないか
そこまで言ってたっけ。
>>186 たまにこのスレを斜め読みするものとしては
そういう話が定期的に回ってくれると
自身の無知加減がよくわかるから助かるよ。
basic_stringって曰くがあったのか・・・(´・ω・)
標準化委員会はSTL自体が「失敗作だった」って 認めてたぞ
標準化委員会はC++自体が「失敗作だった」って 認めてたぞ
親は
>>192 自体が「失敗作だった」って
認めてたぞ
俺は「性交作だ」って聞いた
おあとがよろしいようで
100個ぐらいの文字列を入れて そのなかで一番出現率が高い文字列を探すには STLのどんなデータ構造とアルゴリズムをつかえばいいでしょうか?
まず服を脱ぎます
次にソートします
かぜひきました
相当大変な事態ですね。
手術は成功です
そーっとしておいてくださいね
203 :
デフォルトの名無しさん :2008/10/28(火) 21:27:19
真面目な解答お願いします
std::map<string,int>で出現頻度数えれば?
質問です。 struct a { func() {} }; struct b { vector <a> va: }; とあって、for_eachアルゴリズムでva内のfuncを呼び出すには どのような書き方をすればいいのでしょうか?mem_fun_refと bind2ndを組み合わせるのでしょうか?
自己解決しました。mem_fun_refだけでいいようです。
>>204 連想配列ですよね?stringがキーでintが値ってことですか?
hash
map<string,int> mとすると、m[str]++としてあとはソートなりなんなりすりゃいい
map<string,int> test; test["hoge"]++; sort(test.begin(), test.end(), greater<int>()); こうですか?
mapってソートできないだろ 挿入した時点でキーで自動的にソートされてるんだから 全部要素を挿入したらvectorにでも全要素をコピーして 今度はint基準でソートすればよい
なるほど。どうりでコンパイルが・・・ ちょっとやってみます
vectorにキーと値の構造体をコピーするんでしょうか? 最大値を知りたいのではなく、最大値をとるキーをしりたいんです
脳味噌を使え脳味噌
何か汚ねえなあ・・・lambdaを使わないとやっぱ綺麗に書けんわ struct Comp : public std::binary_function<std::pair<std::string, int>, std::pair<std::string, int>, bool> { bool operator()(const std::pair<std::string, int>& v1, const std::pair<std::string, int>& v2) const { return v1.second < v2.second; } }; void print(const std::pair<std::string, int>& v) { std::cout << "string = '" << v.first << "', count = " << v.second << std::endl; } int main() { std::map<std::string, int> msi; std::vector<std::pair<std::string, int> > vsi; msi["abc"]++; msi["abc"]++; msi["abc"]++; msi["abc"]++; msi["abc"]++; msi["def"]++; msi["def"]++; msi["ghi"]++; msi["ghi"]++; msi["ghi"]++; msi["ghi"]++; for (std::map<std::string, int>::iterator pos = msi.begin(); pos != msi.end(); ++pos) vsi.push_back(std::make_pair(pos->first, pos->second)); std::sort(vsi.begin(), vsi.end(), Comp()); std::for_each(vsi.begin(), vsi.end(), print); }
わざわざmapにするいみあんの?
なんか複雑ですね・・・ ちょっと解読してみます
ああ強いて言えば挿入が速いか・・・
「一番」出現頻度高いのが欲しいだけなら、わざわざソートまでする必要なかろ O(n)で済むぞ
mapに突っ込んだ後で、単に全舐めすりゃいいだろ シークエンスの最大値を求めるのにいちいちソートするのか?お前さんは
まあそうだな イテレータを回すだけ 最大値が知りたいだけならそれでいい
まあただ最大値の文字列の候補が複数あった時は少々工夫が必要か
最大値にタイがある場合も考慮せにゃならんな 単純でいて意外と深いのかもしれないw
int main(){ string str; map<string,int> test; int maxval=0; int maxkey; test["hoge"]++; test["hoge"]++; test["huga"]++; map<string, int>::iterator itr = test.begin(); map<string, int>::iterator itrEnd = test.end(); while(itr != itrEnd){ itr++; } } こうしたんですが、値自体はどうやって参照するんですか?
itr->second
ああそうかpairのコンテナなんですよね
int main(){ string str; map<string,int> test; int maxval=0; string maxkey='\0'; test["hoge"]++; test["hoge"]++; test["huga"]++; map<string, int>::iterator itr = test.begin(); map<string, int>::iterator itrEnd = test.end(); while(itr != itrEnd){ if(itr->second >maxval){ maxval = itr->second; maxkey = itr->first; } itr++; } cout << "maxkey:" << maxkey << endl; } コンパイルはできるんですが、とまります・・・
タイを考慮しても2回舐めればいいだけだから、たいした問題ではないか なんちって
タイがあっても3つ以上はことはないとおもうんで、大丈夫そうです。 しかし動かないです・・・
>>229 >string maxkey='\0';
が良くない。これはstring maxkey=NULL; と同じ意味になる。
つまりアドレス0をアクセスする文字列で初期化しようとする。
基本からやった方がいいんじゃ・・・
>>233 if文内で代入するので問題ないかと思ったんですが・・・
>つまりアドレス0をアクセスする文字列で初期化しようとする。
??
微妙に誤解を招きそうなので訂正 ×つまりアドレス0をアクセスする文字列で初期化しようとする。 ○つまりアドレス0から始まるC文字列で初期化しようとする。 処理系によっては文字列が大きすぎて止まり、他の処理系では アドレス0をアクセスするのでセグメントエラーで止まったりする。
正しくはstring maxkey=""; あるいは単にstring maxkey でいい。
>>235 charだけを引数に取るコンストラクタがないため、
暗黙の変換でconst char*を引数に取るコンストラクタが呼ばれてしまう。
わかりました。親切にありがとうございました
つーか、'\0'はintじゃね?
あとまだ質問が・・・ map<string,int> test; while(){ if(条件){ } } として、条件が成立したときだけ、testを初期化(すべてのキーに対して値を0にしたい)したいのですが、どうすればいいですか?
>>240 だから、std::string::string(0) が呼ばれてしまう。
この意味をよく考えてみろ。
>>241 イテレータを回して全てのsecondに0を代入するしかないだろ
if(){ map<string,int> test; } ではだめですか?
>>244 それはまずい。if文の外側のtestが隠蔽されてしまう。
ネタとマジレスの見分けがつかない
map<string,int> test; while(){ if(){ map<string,int> test; } } でもですか?
決して釣りとかじゃありません。知識不足ですいません。
釣りじゃないなら ・差し当たってSTLよりも先にstringの予備知識を付ける ・スコープの意味を理解する これは最低限やっておく事をお勧めする
わかりました!ありがとうございました
while(itr != itrEnd){ itr->second = 0; itr++; } 初期化はこんな感じですかね? firstのstringの初期化もいりますか?itr>first="";としたらコンパイルできなかったので・・・
itr->firstはconstだろが。 なんでそんなことがしたいんだよ!
>>252 お前は一度STL標準講座の本を買ってきてサンプルプログラムを
全部手で打ち込んで走らせて実行してみろ。
俺はそうやって覚えた。
252の質問はわすれてください!whileでインクリメントしてたitrをbeginに設定しなおしてなかった・・・
学習の初期なら、ヘタすりゃ一日100個はつまらん疑問(後から考えれば)が浮かぶもんだが、 その頻度でいちいち書き込まれちゃかなわん。 ていうか、ある疑問を自力で解こうと動く過程で、副作用的に身につく多くの事柄こそが 実質的には学習のメインだと思うんだが(疑問を1つ解決する度に、幾つもの新知識が身につく)、 いちいち質問してたらその一番大事な効能が激減するぞ。
至言
つか、STL以前の問題ばかりだな
>>240 C では int だけど C++ では char 。
260 :
240 :2008/10/29(水) 08:55:46
>>242 あほ。
文字列リテラルに文字を突っ込む馬鹿じゃねーよ。
勝手に他人認定するな
考えてみろ、と言われても 何も考えず「あほ」呼ばわりする程度には馬鹿なんですね。
あほだし仕方がない
>>258 だからあのときあれほどC++相談室とスレ分けるなと言ったのに・・・
>>264 一緒にしたら荒れて収拾付かなくならなくないか?
C++相談室が過疎ってるから丁度いいのかもしれんけど
初心者スレに行くべきだと思う
リストの中身をAの順で並び替えて、A同士が連続したままになるように Bの順で並び替えるにはどうすればいいの?
Bでソートした後 Aで安全ソート ってことか?
>>267 あ1 あ2 あ3 い7 い9 う4 う5 う6
てな感じ?
stable_sort
期待通りの並てになるまでランダムに入れ替える
きたいどおりのなみて?
お前らボゴソートさんをあまりなめない方が良い。
勿論、ギャグですが。
イテレータを保持して参照しようとするとエラーが出る erase()はしてない、参照前にpush_back()をした push_back()すると以前のイテレータが無効になるのか?
>>277 無効になるコンテナもある。vectorとかdequeとか。
無効にならないコンテナもある。listとかmapとか。
まさにvector 場所を保持できないので必要なデータをとるときに 最初から検索しなきゃならないので不便だな listに変更する
vectorなら単にインデクスアクセスすりゃいいんじゃね?
インデックスも保持しといたらあてにならんだろう
push_backしかしないならインデックスは変わらんだろ
インデックスはとある理由で禁書されている。
push_backしかしない場合、dequeのイテレータは無効になるが 参照やポインタは無効にならない。 微妙に便利な時もあるかもしれない。
push_backしかしない場合インデックスは変わらないだろうけど 参照とかポインタは変わるだろ
vectorならな dequeだと変わらない
dequeもメモリ続いてるから、足りなくなったら再確保されてアドレス変わらね?
> An insert at either end of the deque invalidates all the iterators to the deque, > but has no effect on the validity of references to elements of the deque. 先頭と末尾への挿入は、イテレータは無効にするが要素への参照は無効にしない。
↑は規格書の 23.2.1.3 deque modifiers のところね。
>>287 deque<T>の仕様をとてつもなく乱暴に要約すると、
vector<T*>みたいな構造になってる。
だから拡張されても要素自体のアドレスは変わらない。
ちなみに両端以外への挿入はイテレータも参照も無効になるから注意
>>287 ランダムアクセスできるだけでメモリは続いてないでしょ?
とうとうお前らがdequeのスゴさに気づく時が来た
いや知ってて当たり前のことばかりだから
dequeの使いどころがわからん
上から取ったり、下から取ったり、南京玉簾のような使い方をする場合、dequeほど使えるコンテナは無いぞ。
「dequeは結構すげえんだぜ!」 っていうデータをまとめた記事(英語)が以前貼られてたね。
>>295 ・ランダムアクセスしたい
・要素を加えたり抜いたりすることがある
そういうときに使う。
vectorでやると要素の追加・削除で領域を連続にするためのコストがかかる。
listはイテレータを記録すれば、ランダムアクセスできるよね? イテレータが無効になる場合ある?
つうかイテレータ記録すればどんなコンテナだろうとランダムアクセスできるんじゃね
話の焦点が「イテレータを記録するモノ(コンテナなり何なり)」の機能に移るだけだよな、それ。
>299 結局 vector<list<something>::iterator> みたいなのを使うことになって vector が登場する罠
つまり boost::multi_index の話しに
dequeのbuffer sizeってなんぼぐらい? vc7,8は16bytes gcc3.4.4(cygwni)は512bytes vcの16って小さくね? stringなんかはlistと同じになっちゃわないか このサイズを指定できるdequeがほしいんだが boostにあったりするかなあ
すみませんです。 listのiteratorって、 要素の追加とか削除とかして要素数が変わってしまっても、 そのまま使える保証はあるんでしょうか? 要素の参照は保証されている思うんですが、iteratorが使えるのか。 VCでは実際動くみたいですが言語仕様的にいかがなものか。 ぜひアドバイスおねがいします。
保証されている。アドバイスとしては仕様書読め。
付け加えると削除したイテレータ自体は当然無効になる。
308 :
sage :2008/11/02(日) 03:15:01
早速の返答ありがとうございます! ブラボーlist!使いやすさ爆発です。 そして以後ちゃんと仕様書読むようにします。 ありがとうございました。m(_ _)m
VC使ってる時点で言語仕様も糞も無いと理解しろ。
VC++6.0の頃じゃないんだから 今は結構まともだよ
むしろgccのほーが異端
それはない
MFC(笑) ATL(笑)
急にどうした?
dcc最強
ecc最強 翻訳的な意味で
BCCはどうよ C++Builder2009にはBoost標準添付だったが
Boostって行っても1.35、しかもフルセットでなくてサブセットだけどな
320 :
デフォルトの名無しさん :2008/11/05(水) 11:45:38
map<string int> hoge; mapを宣言したとき、intの領域は初期化されているんでしょうか? されていないとしたら、 map<string,int>::iterator itr; map<string,int>::iterator itrEnd; itr = hoge.begin(); itrEnd = hoge.end(); while(itr != itrEnd){ itr->second = 0; itr++; } のように初期化すればいいんですかね?
ちがう
なんで初期化したいんだろうか
intのほうでカウントとりたいんです
map<string int> hoge; だけだと map コンテナの中身は空っぽだから string も int もまだ領域確保されていなくて デフォルト初期化も値初期化もはじまっていない 空のコンテナの begin() と end() は無効な要素を指している 無効な要素に対するアクセスは失敗する itr->second = 0; // やっちゃらめぇ だと思います
空のコンテナなら begin() == end() にならないんだっけ?
そうなるなら
>>320 を走らせちゃってもアクセス違反にはならないが
>>324 なるほど
void func(){
map<string int> hoge;
}
の関数内で宣言した場合、関数が呼び出される度に 空っぽになるんでしょうか?
呼び出される度にbegin()==end()になります
hoge["str"] ++; とやればちゃんと0から加算されるんですか?
空のコンテナのイテレータはbegin()==end()になるって保証は 規格書に書いてあるの?
>>328 規格ではmapにoperator[]を適用した場合もしそのキーが
存在しない時はデフォルトのコンストラクタで初期化される
決まりになってるからint()、つまり0から始まる
iteratorの位置を動かすとき ++it とかするけど it+=8 のような感じで8個分移動する方法はないの?
もちろん、ランダムアクセス可能なイテレータはit += 8で平気。
listなのでループで回すしかないか あと、ある値を持つコンテナを検索する関数を作ったのだが 見つからなかった場合NULLを返そう思ったら itにNULL代入できない。しかも it ==0とか演算も不可 このような場合みんなはどうしてるん?
thx、打開した
そもそもfindでいいんじゃね
stlportのhash_mapにお尻から回す奴はないですか?
イチジク浣腸はどうだ
rbegin() rend()
叙述関数には引数わたせないの? find_if( List.begin(), List.end(), compare( 引数1 、 引数2 ) );
ファンクタを使えばいくらでも。
>>342 vcのstdext::hash_mapならreverse_iteratorがあるぞ
VC2008とSTLpらすか5.1.7ですけど _STLP_USE_STATIC_LIBを指定すると ↓と言われてリンクできません。 ファイル 'stlportstld_statix.5.1.lib' を開くことができません。 stlportstld_static.5.1.libならあるんですけど。バグですか?
ren stlportstld_static.5.1.lib stlportstld_statix.5.1.lib
#define _STLP_NEW_PLATFORM_SDK 1
351 :
デフォルトの名無しさん :2008/11/08(土) 12:18:23
VB6からVC++2005にプログラムを移植してるんですが、 下記の処理がVB版に比べてVC++版では50倍ほど時間がかかりました。 1から順に使われていないID番号を探すアルゴリズムで、内容は全く同じですが、なぜでしょうか? m_itemは構造体配列で、要素数は600個程度です。 VC++のstd::vectorの実装はクソすぎなんでしょうか? ■VBの処理 Dim i As Long, j As Long For i = 1 To 65535 For j = 0 To m_item_num - 1 If m_item(j).id = i Then Exit For Next If j = m_item_num Then get_new_item_id = i Exit Function End If Next ■VC++の処理 size_t i, j; for( i= 1; i< 0xFFFF; i++ ){ for( j= 0; j< m_item.size(); j++ ) if( m_item[j].id == i ) break; if( j == m_item.size() ) return i; }
>>351 const size = m_item.size();
for(j = 0; j < size; ...
キミのままだと、jのループ後とにm_item.size()関数が評価される。
VC2005だとm_item[j]が毎回範囲チェックされてる vector使う前に #define _SECURE_SCL 0を入れると良い感じらしい あと、まさかとは思うけどDebug版じゃなくて Release版で実行してないとかはないよね?
そもそもループを1重に直したら(VBでもC++でも)もっと速くなると思う。
setでも使えばいいのに、とも思った
VBは知らないけど、C++のただの配列とvectorとでも50倍も差はないから、なんか他の要因で遅くなってると思われ。
あーごめんそれは無理か
終了条件おかしくないか?
351ですが、
>>352 が主な原因だったようです。
>>353 でも多少改善しました。
二重ループをやめて、qsort()でもしてから一重ループで探すというのもいいかもしれませんが、
アルゴリズムを変更しないとVBより遅くなるというのは腑に落ちませんね。
ベクターは使い方次第でパフォーマンスに劇的に影響するようで、なんか怖いです。
VC2008のvectorで if (int i = 0; i < tbl.size(); i++) tbl[i] ・・・ みたいな使い方と、 配列で、 if (int i = 0; i < TBL_SIZE; i++) tbl[i] ・・・ みたいな使い方をした場合、 Debugビルドで最適化なしだと数十倍の差で、Releaseビルドで、最適化ありだと、二倍程度の差だった。
このスレ的にはiterator使おうぜ
>>359 VB知らないんだけど、この場合のm_item_numってなに?
それ次第では、そもそも「内容は全く同じ」という認識が間違ってたことに。
VBとコードが違わないか?
>for( i= 1; i< 0xFFFF; i++ ){
for( i= 1; i<= 0xFFFF; i++ ){
調べてる要素が違ってるなら50倍違ってもおかしくはないけど。
あとは計測時間が短すぎて時間を計ってるタイマーの精度の違いが出てるとか
とりあえず
>>351 のコードをReleaseビルド&_SECURE_SCLでコンパイルしてVBより50倍も遅いなんてことあり得ないだろ。
>359 ちゃんと最適化かけたか?
STLがVBに負けるなんて悔しい ビクンビクン
366 :
351 :2008/11/08(土) 15:08:04
すみません。デバッグビルドになってたようです><
なんかデバッグなしにしたり最適化とかするとエラーが出てコンパイルできなかったので、何となく諦めてました。
>>359 をやった上で最適化まですると、VBより速くなりました。
めでたしめでたし。
しね
まさにVB脳
二重ループのかわりにstd::find_ifを使ってみようぜ! あと上で言ってる人もいるけどsortするならむしろstd::vectorのかわりにstd::setを使おうぜ Itemがidをもつぐらいなら用途にあってる可能性高いし
VBでもデータ構造を変えれば劇的に速くなるな。
>>369 ちょっとよく分かりませんが、勉強してみます。
今はVBのコードをC++にツラツラ置き換える作業だけをやってます。
VBの配列 → std::vector
VBのString → std::string
という置き換えで、今のところこれ以上のSTLの知識はありません。
アルゴリズムを下手に変えると、新たにバグが混入することになるので。
VB6と一緒に心中してくれよ。こっちくんな。
移植させてもらえるだけでも素晴らしいことだと思わないか。
つうか既にバグ混入しててワロタ >for( i= 1; i< 0xFFFF; i++ ){
findを使って作ってみました enum { N = 600, ID_MAX = 0xffff }; template<typename ID> struct Compare { Compare(ID i) : m_i(i) {} template<typename T> bool operator()(T const& i) { return i.id == m_i; } private: ID m_i; }; template<typename ID, typename Container> ID find_uniq_id(Container const& m) { typename Container::const_iterator m_end = m.end(); for (ID new_id = 1; new_id <= ID_MAX; ++new_id) { if (std::find_if(m.begin(), m.end(), Compare<ID>(new_id)) == m_end) return new_id; } throw std::domain_error("new_id must not be beyond ID_MAX"); }
376 :
375 :2008/11/08(土) 17:05:13
id_typeとget_idを特殊化することによってより流用できるようにしてみました 参照の参照が怖いのと面倒臭いのが難点だと思いました template<typename T> struct id_type { typedef typename T::id_t type; }; template<typename T> typename id_type<T>::type get_id(T const& x) { return x.id; } template<typename T> struct Comparator { typedef typename id_type<T>::type ID; typedef bool result_type; Comparator(ID i) : m_i(i) {} bool operator()(T const& i) const { return get_id<T>(i) == m_i; } private: ID m_i; }; template<typename ID, typename Container> ID find_uniq_id(Container const& m) { typename Container::const_iterator m_end = m.end(); for (ID new_id = 1; new_id <= ID_MAX; ++new_id) { if (std::find_if(m.begin(), m.end() , Comparator<typename Container::value_type>(new_id)) == m_end) return new_id; } throw std::domain_error("new_id must not be beyond ID_MAX"); }
これはひどい
なんというオナニー
数値を文字列にするには ostringstream を使用する方法がメジャー?
>>379 たぶん sprintf を使う人のほうが多い。
snprintf が C++ 標準に入ればさらに増えるかもしれない。
結果を string で使うことや安全性を考えれば ostringstream のほうが良いとは思うけど。
sprintfはchar確保するの面倒だとおもうけど 利用者が多いのは何か理由があるの?
Exceptional C++ Style でstringstreamはsprintfに比べて だいたい10倍くらい遅いと書かれていた。
速度的な点もあるけど printf系というのは非常に多くの言語で(Win32にはAPIもある)用意されていて 細部の違いはともかく、知っている人が多い、使い方を覚えて無駄にならない、 というのもある。 C++だけの世界だけで見れば型安全性の無さ等非難される面も多いし 「C++らしくない」という良くわからない理由で嫌う人も。 また、(よく知らない人に多いが)セキュリティ等の面で問題があると言い張る人も居る。
書式の設定がめんどくさい上に、長くなってしまう気がするんだが俺の書き方悪いのかな
>>385 stream のことなら、たぶんそんなもん。
そういえば C++0x でもこの点は特に改善されたような話を聞かないな。
boost の io state saver ぐらいは入ってもよさそうなもんだと思うけど。
>>379 boost::lexical_cast を使うがよい
結局 stringstream 使ってるんだけどな
388 :
デフォルトの名無しさん :2008/11/09(日) 11:53:14
>>381 char確保しなくてもいいよ。
std::string str;
int a = 123;
str.resize(256,0);
sprintf((char*)str.c_str(), "%d", a);
str = str.substr(0, str.find('\0'));
stringにconst_castか…
c_strの間違いw
>>388 c_str() の戻り値に無理やり書き込んでも反映されるとは限らんよ
っていうかconst外して書き込むなんて無茶苦茶にもほどがある
#include <vector> #include <cstdio> #include <iostream> int main(int, char *[]) { std::vector<char> buf(0xff, 0); int n=10000; std::sprintf(&buf.front(), "%d", n); std::cout << static_cast<const char*>(&buf.front()) << std::endl; return 0; } なるへそ
printf系はセキュリティ面で問題あると思ってたが 問題ないの?
const外し か、漢だ!
nの型がintでlog10(n)が100や200にもなるアーキテクチャがあれば教えて欲しいものだ
string使おうがvector使おうが スタック上に領域確保してれば char配列となんら変わらん
>>393 使い方の問題。
ユーザー入力をフォーマット文字列に使おうとする大バカと
最大文字数の指定方法を知らないバカがそう言ってるだけ。
>>398 具体的に何の関数を言ってるかわからんけど、
すくなくともsprintfはあぶない
一般的にやるべきでないとされていることを「だって出来るじゃん」の一言でやってしまう・・・ くせぇーっ! DQN以下の臭いがぷんぷんしやがるぜぇーっ!
>>399 具体的にどこが危ないのか教えてよ
「使い方を間違えたら危ない」というレベルの話なら
「listen()を使う全てのプログラムは危ない」というのと同じになっちゃうから
>>401 え?最大文字数を指定できないじゃん
それが危険だと思えないならまぁ好きにするといいよ
sprintfで100byteのバッファしか取っていないのに、 100文字以上有るかもしれないユーザ入力を与えるとかね。
VCのsprintf_s使ってます(^^)
ハア? char buff[100] sprintf(buff, "%.80s", user_input); これのどこが危ないって?
まさしく
>>398 の最下行に書いてあるバカが言ってるとしか思えないんですけど。
C++ で何で sprintf なんて使ってるのん? しかも STL スレで・・・。 ostringstream か boost::format を使っとけ。
>>405 そういうことを分かって使う分にはいいけど、
実際に使う人間が必ずしも分かっているとは限らないし、
分かっていても、うっかりやってしまう危険性があるよね。
つうかそんな単純なケースならいいけど、 色々出力したりロケールが絡むと出力結果の予想がしんどいだろ
そんなレベルなら、「vectorで[]は使わないほうが良い。at()を使え。」と同じじゃないの。
特に
>>399 はわざわざ
>>398 に対して言ってるんだから
もっとちゃんとした危険性を指摘してくれても良さそうなもんだけど。
そりゃ、切捨て前提という仕様は良くないとか
全部生かすつもりならsnprintfの方が楽だとか言うのはその通りだけど
それとセキュリティ的な問題は全く別だから。
柔軟性だって例えば
std::vecotr<char> buff;
buff.resize(???);
sprintf(&buff[0], "%.*s", buff.size()-1, str);
のような使い方である程度確保できるし。
>>409 「使いやすさ」と「セキュリティ的に問題」は全く別の話なんですけど。
>>410 > 「使いやすさ」と「セキュリティ的に問題」は全く別の話なんですけど。
この一行が
>>409 の話とは全く別の話なのは、そういうジョークなの?
ostreamが状態を持ってるのもしんどい
あ、別にユーザー文字列をそのまま配列に落とす場合に限らないよ。 そもそも(1箇所での)ユーザー入力なんて、普通は1つなんだから 例えば sprintf(filename, "file-%.80s%d.dat", input, num); のような形式でも、充分に最大値は予想できるし。 あ、「intが512bitの環境を考慮すると面倒」というのはその通りか。
使い難さが有るということは、ミスり易いってことじゃね? ミスってもセキュリティ的な問題が出ないライブラリならいいんだけど。
いわゆる、バグというものは、ミスることによって起こるんだから。 十分予想出来るとかで大丈夫じゃないか、なんていい方出来るだったら、 世の中の全てのソフトウェアにはバグが無いってことも言えてしまう。
416 :
409 :2008/11/09(日) 14:19:58
>>410 いやだから
出力結果の予想が困難→バッファ長の予想が困難
セキュリティ的にあぶなくね?
という話し
気をつけて使え
って話しなら
そうですね
としか言えないけど
みなミスりがちだからsnprintfとかVC++のセキュア関数とか
あるんじゃないの?
いやだから
全然
>>398 への反論になってない。
「使い方を知らないのが問題」なだけでは
「セキュリティ的に問題がある」ということにはならないから。
まあ、416の言いたいことはもっともだし
他にもっと良い選択肢があるならそちらを使うべきなのは確か。
でも残念ながら標準ではない。
ただ、自分が「使い方を知らないバカ」だという自己紹介はもういいよ。
>>398 の最下行を無視して
>>402 と反論するような人が
>>399 みたいに書くわけだから。
あ、それと、「最大値の見積もりを間違える」点についてだけど
別に用意したバッファの95%以上まで使わなければいけない、というような決まりはないから。
多少(例えば末端の'\0'とか)の計算ミスがあっても充分すぎるように見積もって置けばよい。
例えば
>>405 のようにね。
>多少(例えば末端の'\0'とか)の計算ミスがあっても充分すぎるように見積もって置けばよい。 ええええー
最大量がきっちり分かってる状況じゃないかそれでいけるのは
は?
当然過ぎて困りますが
ユーザー入力の部分の最大量は
>>405 のように制限して
その上で他の部分の見積もりが多少違っていても大丈夫なように
ということですけど。
ユーザー入力の部分の最大値を制限するのは 当然というか大前提だと思っていましたが、皆さんは違うのですか。 認識の違いですね。
つまり、%fは使うなってことですね、判ります。
あー、sprintfは使い方が難しくセキュリティ的な問題を起こしやすいので使うべきではない。 とすると、 同じように、 使い方が難しくセキュリティ的な問題を起こしやすいものは使うべきではない ということになりますね。 つまり、 C++をやめましょう、と。 Javaあたりがよろしいでしょうか。 実際、世間の潮流もそういう流れになってますしね。
>>425 sprintf(buf, "%10.0f", 1e100);
snprintf()なら、
snprintf(s, sizeof(s), …
ってやっとけば安全だけど、
sprintf()は人間が数えないといけないじゃん。
>>405 見たいな単純なやつだったらどっちでもいいってことになるかもしれんけど、
書式が複雑になってくると、ミスる可能性がでてくるよ。
てか単純にsnprintf()のほうが楽ジャン。sprintf()で人間がバッファサイズ数えるなんて非合理。
いつまで STL スレで sprintf の話をやってんだよ。 そんな型安全じゃない C の糞遺物なんぞ C++ で使うな。
だよな!
>>426 printf("%.2u", -1);
の時に必ず2桁に収まると思う人は居ませんね。
これと同様に最大桁数が見積もれる点は変わらないと思いますが。
いや、最大桁数はbit数に依存するので環境依存ですけど。
>>427 だからsnprintfはC++においては非標準だって。
それに「sprintfはセキュリティ的に問題がある」という意味にはならないよ。
「C++はセキュリティ的に問題がある」というのと同様。
ところで型安全って何ですか?
snprintfってC99からなんだっけ… 0xでは標準になるのかなぁ
なりません
相変わらず話題の質が下がると賑わうな。
>>432 ドラフト N2798 の 17.1 [library.general] p9 より
> This library also makes available the facilities of the C99 standard library,
> suitably adjusted to ensure static type safety.
_scprintfで数えたらいい
>>430 doubleの最大桁数を常に見込んでバッファを確保するとでも?
%fを使わずに、素直に%gを使えば済むじゃん。
そういう使いこなしを必要とするからsprintf()は難しいと言うなら判るが、
使いこなしてもいないのに語ろうとするな。
結論:ostrstream or boost::lexical_cast or boost::format or boost::egg::to_string
結論:いままで聞いた話を総合すると、一番スマートなのはこれ。 std::string str; int a = 123; str.resize(12); sprintf_s((char*)str.c_str(), str.size()-1, "%d", a); str.resize(str.find('\0')); ストリームとかで中間バッファを使うのはメモリの無駄だし、sprintfの書式指定能力の高さは最強。
>>439 その場合だとstr.size()は0が返るよ。
あと規格は大切にね。
>>その場合だとstr.size()は0が返るよ。 ごめん勘違いした。 でもその書き方は受け入れられない。
c_str()を出力バッファに使う男の人って
もはやSTLじゃねーなw
vectorを使えばかろうじてSTLに関する話題の範疇に入…らないか
>>439 × (char*)str.c_str()
○ &str[0]
あと、せっかくだから sprintf_s() の戻り値使えよ。
>>445 規格ではstd::stringのメモリ上の連続性は保証されていない。
std::vectorと混同するな
どうせ大丈夫なんだから別に良いじゃん
仕事で一緒にならないなら別にいいよ
>>446 C++0x で連続性は保証されるようになるし、
現状のどの実装でも連続性は成り立っている。
size_t count = _sctprintf(_T("%d"), 777) + 1; std::vector<TCHAR> buffer(count); _stprintf_s(&buffer[0], count, _T("%d"), 777);
TCHAR(笑)
>>449 そういう話をしたいのなら実装依存スレへ逝け
>>451 そういう話をしたいのなら実装依存スレへ逝け
STLのlistを利用したプログラムを実行中、 "list iterators incompatible" という例外が発生しました。これはどういったエラーでしょうか? 開発環境はVisualStudio2005 AcademicEditionです。
ソース晒せ
transformの使い方に関して質問があります。環境はGCCです。 目的は、stringの中身をすべて小文字に変換したいのです。 #include <string> #include <algorithm> #include <cctype> #include <cstdio> #include <iostream> string aa = "AbCdEfG"; transform(aa.begin(),aa.end(),aa.begin(),tolower) で、aaの中身をすべて小文字に変換できません。 理由はわかりますでしょうか?
>>457 とりあえずコンパイルエラーだろ。
エラーの意味がわからんということならエラーメッセージ晒せ。
俺の環境では全部小文字になるが・・・。
使用したソース #include <string> #include <algorithm> #include <cctype> #include <cstdio> #include <iostream> using namespace std; int main(){ string aa = "AbCdEfG"; transform(aa.begin(),aa.end(),aa.begin(),tolower); } 以下がコンパイルエラー test.cpp: In function 'int main()': test.cpp:9: error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits\ <char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> \ > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded f\ unction type>)' よろしくどうぞおねがいします。
Effective STL に乗ってたネタかな
>>457 たぶん、こういう関数オブジェクトを作ってそれを渡せばいいよ。
struct my_tolower : std::unary_function<char, char>
{
char operator ()(char c) const
{
return std::tolower(c);
}
};
transform(aa.begin(), aa.end(), aa.begin(), static_cast<int(*)(int)>(tolower)); 通った typeof(aa)::value_type : char tolower : int(*)(int) でtolowerをchar(*)(char)と型推論しようとして失敗してる なので正確にキャストして与えてやればおk?
>>461 まずはデバッガのバックトレースを見たりブレークポイントつかったりしてあたりつければいいよ
segvだろうが、unhandled exceptionだろうがどこで発生したか分かるから
>>464 >>460 の最後の行の中にunresolved overloaded function typeってのがあるでしょ。
C++では、tolowerが多重定義されているのだが、
それではテンプレート引数の型が決定できないということでエラーになる。
だから、
>>464 のようにキャストが必要になる。
>>463 みたいに他の方法も考えられる。
>465 ありがとうございます。とりあえずどこで投げてるのか絞り込んでみます。 ただ、list iterators incompatibleというのがどういう状態を指すのか、よくわからないのです。
vcのstlのincludeディレクトリにて"list iterators incompatible"で全文検索するとか
>469 そういう方法もあるのですね listの中を覗いてみます。 ありがとうございます
dequeにpush_backで要素を挿入していくのは、予め配列をサイズ決め打ちで宣言して代入していくのより遅いですか?
>>471 速度は実測が基本。
一般的に、 push_back() を繰り返す場合、配列要素のメモリ確保回数が増えるので
遅くなる可能性が高くて、それでも push_back() ならコピーコンストラクタが使われるので
要素の型によっては代入に比べて速い可能性もある。
気になるけど図るのが面倒臭いなら、reserveしておけば精神的に気が和らぐ。
vectorならreserveは必須だと思う dequeってどうだろう
dequeはある一定の長さのブロックが不連続に確保されるそうだから reserveしたらシステムからメモリを持ってくる時間は稼げるけどvector と違ってメモリの再配置は起きにくいんだよね
それは実装によるんでは。
実装によるのはもちろんだが一般的な実装の話ね
dequeのpush_backが(償却じゃなくて正真正銘の)定数時間であることは規格で要求されてたはず だから一概に実装に依るとも言えない
dequeはpush_back/push_frontで既存要素のコピーが起こりえないのがありがたい まあ最初から要素数が判ってるならvector一択だけど
STLのことは良く分からないけど、 list,stack,queue,vector,dequeで空のクラスSampleのポインタを、 10万個格納、(1個delete&削除・1個格納)*10万回、 空になるまでdelete&要素削除 してみた。 vectorは予め追加要素の2倍reserve()した。 要素の追加削除はvector,stack以外『古い物から削除』、前から取り出して後ろから追加でやった。 stack、queueはそれぞれコンテナdequeを利用。 list 68.11 秒 vector 20.344 秒 stack 27.5 秒 deque 9.468 秒 queue 9.438 秒 queueが速すぎてワロタ dequeは操作する方向次第でstackとほぼ同等 queue,stack,dequeはこの場合、実質同じモノだし queue,stackのコンテナを変えたら悲惨な結果になった PCが悲鳴を上げたのでこれ以上のテスト回数は勘弁
あぁ、次はboost::circular_bufferだ…
>481 >480と同条件、上限20万個として計測してみた。 平均5.5秒くらいだった
ひょっとしてlistってあんまり使わない方が良い?
むしろ連結リストのくせに良い数字が出てると思うがね
>>483 状況次第
listのほうが向いてる使い方もあるしね
途中(先頭末尾以外)の要素の削除はlistじゃないとやってられんやろー
あとリストの連結やリストの分割もあるか あれ?そんなことできたっけ・・・?
とりあえずただデータを突っ込んで置きたい(出し入れ順番とかどうでも良い)場合には、 リストは不向きってことか
昔はやたらとリンクリストを使うのがいいとされていたが、 今のご時世でも初心者にリンクリストを教えたがる間抜けが後を絶たない。 普通にstd::vectorを使えるように仕込んでおけば、std::listを使うのも苦労はないだろうに。
>>487 途中の削除もdequeは結構速い。
listは削除してもイテレータが無効にならないのが利点かな。
492 :
1/2 :2008/11/14(金) 15:46:52
listを使っていてよく分からない事態に遭遇したので質問します。 長くなってしまったので申し訳ありませんが分割投稿します。 環境:VC++2005 / XP typedef struct globalArray { int type; char name[100]; float variable[5][5]; } globalVar; typedef struct nodeDat { CShaderNode *nodeKind; globalVar varDat[5]; // 上の構造体(globalVar) int dataNum; float power; } nodeData; typedef struct _data { nodeData mainNode; // 上の構造体(nodeData) nodeData blendNode; // 上の構造体(nodeData) nodeData subNode; // 上の構造体(nodeData) int materialNum; dxMaterial *matrials[MAX_MATNUMBER]; } dataBlock;
493 :
2/2 :2008/11/14(金) 15:47:25
上のような構造体が有りまして、一番下のdataBlockをリストとして扱っているのですが、 dataBlock tmp; /* 〜 データ作成処理 〜 */ /* 〜 挿入先探索 〜 */ insert(itr,tmp); とデータを挿入してリストを覗くと途中までしか正しくデータが入っていません。 データ作成過程で"",NULL,0.0fと全て初期値を用いてデータを初期化しているのですが、 data[0]->mainNode.varDat[0].variable 以降のデータが未初期化のまま生成されています。 構造体を入れ子にする前は正しく動いていたのですが、 listを扱う際は構造体を入れ子で扱うとNG等の制約があるのでしょうか。 ご教授お願いいたします。
それだけだと推測しかできん ・初期化の部分が不完全か ・未初期化というのが勘違いか ・リスト操作がバグってるか のいずれかしかないが、心当たりがないなら何か見逃してるんだろう そのようなNG的制約は無いので大丈夫
495 :
492 :2008/11/14(金) 16:04:13
返信ありがとう御座います。 (※(int)はキャストではなく型を説明上明示するために便宜的につけた物です。紛らわしくてすみません。) 例えば仮データ(tmp)で、 (int)materialNumを0で初期化したのがリストのデータでは (int)materialNumが-33686019になってしまっているので、 >・リスト操作がバグってる のでしょうかね…… ありがとうございます。制約は無いときいて安心しました。 もう少し追ってみます。
496 :
492 :2008/11/14(金) 16:30:43
連投失礼いたします。 色々弄ってみたところ、構造体のメンバの記述順を入れ替えると正確に入るデータと入らないデータが出てきました。 詳しく調べたところ、連結しようとしている構造体は180byteで、リストで正しく入るのは96byteの領域まででした。 数字的にこれって多分仕様ですよねぇ……
-33686019ってことは0xfdだろ? ちゃんとdeep-copyせんと。
dataBlock tmpA; /* 〜 データ作成処理 〜 */ dataBlock tmpB; tmpB = tmpA; ってやって、tmpAとtmpBは同じ内容の独立したオブジェクトになる?
誰にもわかりません
500 :
492 :2008/11/14(金) 21:01:27
返信ありがとう御座います。
>>498 さんのを実行してみたところ、同内容の独立したオブジェクトに成りました。
deep-copyなのですが、
/* 〜データ作成処理〜 */
を抜けた後、tmpに全ての値がきちんと入っていることを確認し、
data.insert(itr,tmp);
でインサートを行っているのですがコピーに関してはlist側で処理されている様で、
こちら側からコピー処理を定義することが出来るのでしょうか。
その場合はコピーコンストラクタじゃ?
503 :
492 :2008/11/15(土) 01:20:38
すみません、何かもう全く関係ないところが原因っぽいです。 構造体のメモリ領域と他のクラスのメモリ領域が被ってる……
504 :
デフォルトの名無しさん :2008/11/15(土) 03:13:32
あるIDを割り当てるクラスを作成しようと思っています インターフェースとしてはこんなかんじで class IDAllocator{ uint32_t T AllocID(); void FreeID(uint32_t id); }; クライアントコードに対して、一意なIDを割り当てるのですが、 IDを使い終わった後は返却し、後ほど再利用できる様にしたいです。 IDを割り当てる際に、現在使われてないIDの内、最小の数値のIDを返す仕様にしたいのですが、 STL的にかっちょいい実装方法を教えてください 今のところ割り当て済みのIDをvectorに記録しておいて、0から1ずつ増やしてvectorに無いIDがあれば それを使うというどう考えても効率の悪いやり方でやっています
使い終わって返却されたIDをpriority_queueに記録し、再利用するときはそこから取り出す
priority_queueが空なら新たに生成する→新しいIDは最も大きい数値になる ってことか
インテレータの有効性をチェックする方法はない? 何も代入されてないときなど、別の変数でフラグ保持するのは面倒だと思うので
とりあえずend()でも入れとけとか、 有効/無効状態をチェックするなとか、 そもそもインテレータって何とか。
そんなあなたにboost::optional
>488 splice 使えばできるはず。
>>511 どこがどうおかしいと思うのか書けやカス
とりあえずテンプレートクラスはクラステンプレート
enumの値か?
515 :
デフォルトの名無しさん :2008/11/16(日) 12:14:51
それは別に間違ってなくね
MIRROR_X
問題ないだろ MIRROR_X = SCALE | ROTATE を意図して書いてあるならな。
はー?
enum bitset 二大不要物(笑)
enumを不要とか言うやつは素人
enum要らないとか言う奴はただのバカかTMPしない人だろ
>C言語であれば、ANDやOR等の演算を使って管理しますが、C++ではbitsetが利用できます。 この辺りで馬鹿を晒している。このサイトも勿論、私のダメサイトリストに載っている。
じゃぁbitsetってなんに使うの?
ビット単位のフラグの管理をせざるを得ないときに使うかなぁ。ま、そのときが来たら考えるよ。
>>522 上級者のあなたがおすすめするサイトを教えてください
527 :
522 :2008/11/16(日) 13:23:15
残念ながら今のところ、初心者に安心してお勧めでキルサイトは見つけていない。 したがって、申し訳ないが期待には応えられない。 ちなみに、私のダメサイトリストは正しくは、「初心者にはお勧めできない(≒ダメ)サイトリスト」だ。 中級者辺りが読む分には、(自力で確認できるノウハウもあるだろうから)まぁ、悪くないかもしれない。
enumは型安全じゃないのが気に要らないな
C++のenumは、|=するだけでキャストが必要な糞仕様
俺は#define派 enumだとアセンブラソースから使えないから
>>529 そもそもビットフラグで使うとは限らないわけで…
それは128ビットとかに使うぞ
お前らみんな、unionさんに謝れ!
アマチュアの俺からすると分からんのだけど、unionって実際の業務で使われてるの? enumなんかは割りと使ってるんだけど
>>535 使うこともあるよ。Cでbitsetもどきを実装するときとか。
大きな数値から上位ビットと下位ビット分けたり
・建前 unionは環境に激しく依存するから、使わない方がいい。 ・本音 いまどきビッグエンディアンとか無いだろw
オレも、エンディアン、ビット幅、signedの右シフト、除算の符号は実装決めうちで作ってる
>>538 サーバ系では未だにSunが頑張っているから無視できないのよね。
うにおんは組み込みCで以前使ってた事がある おそらく今でも使ってる
1の補数はもう絶滅でいいだろ
引き算どうすんだよw
負数の表現方法のことだろ。
それは2の補数
よその言語だとASCIIにIEEE754も決め打ちと化しているものもあるよな。
未だにIBMのサーバでEBCDICとかあるから油断できない
>>538 俺はエンディアン入れ替えたいからunion使ってる。
union {
double a;
char b[8];
}
つーかネットワークバイトオーダはbigだし 画像処理でもエンディアン入れ替えなんてよくやるでしょ 全部littleで済むと思ってる人ってどういう世界に生きてるんだ?
意識する場面なんてほとんどないな
>>550 そういうときに、必ずエンディアン変換を挟むコードを書いてしまう(あるいは書かない)
というのがエンディアン決め打ちのコーディングだと思う。
#ifdefるだろjk
いや、自動判断する。 例えばtiffはヘッダのIかMかで判断できるし、実行環境がどっちなのかはint foo = 0とでもして& fooをchar *にキャストして取り出せば判る。
555 :
554 :2008/11/18(火) 00:51:28
s/int foo = 0/int foo = 1/ まぁ、unionは使わないけれど。
スレから脱線するが、標準の方法でエンディアンをコンパイル時に知る方法ってある? 実行時ならできるんだが
boost/detail/endian.hppとかを見る限り、標準では無さそうだね
>>556 コンパイル環境のエンディアンを?
それとも、ターゲット環境?
>>556 VxWorksなら_BYTE_ORDERのdefine見れば分かるが他はしらん。
>>560 お前はSun、IBM、MIPSを敵に回した。
vectorについてですが array.reserve(array.size()); でぴったりのサイズに変わるかと思ったのですが変わりません。 大きなデータを扱ったりする場合、ぴったりのサイズで作り直した方が メモリが節約できるかと思うのですが、なぜうまくいかないのでしょうか。 何かいい方法はないでしょうか?
vector<T>(array).swap(array);
reserveは拡大する方向にしか働かないのでは
>
>>562 §23.2.4.2.2
void reserve(size_type n);
2 Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage
allocation accordingly. After reserve(), capacity() is greater or equal to the argument of
reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation
happens at this point if and only if the current capacity is less than the argument of reserve().
3 Complexity: It does not change the size of the sequence and takes at most linear time in the size of the
sequence.
greater or qrual と書いてあるから等しいかもしくは大きいとなるので
ぴったりのsize()になる保証はない。
おっと
equal to the previous value of capacity() otherwise.
ともあるから、縮小しようとしてもcapacity()は変化しない事になる。
詰まるところ
>>563 のようにスワップ技法に頼るしかない。
567 :
562 :2008/11/20(木) 11:20:10
>>563-566 出来ました。ありがとうございます。
サイズの縮小は出来ないんですね。勉強になりました
今までイテレータが指してるコンテナのことをイテランドと呼んでたんですが そんなの聞いたことないって言われました ぐぐってもほとんど出てこないので不安になってきたんですが(「イテランド」だとゼロ…) 普通に使いますよね?
はつみみです
ぐぐった時点で気づいてるだろwwww俺は聞いたこと無いな iterandにしたら多少出てくるけど、まぁスズメの涙ね
あーやっぱり? iterandは1000件くらい引っかかるから、わざわざカタカナにしないだけで あっちでは普通の言葉かもしれないと思ってたんですが じゃあ皆さんはイテレータが指してるコンテナのことはなんて呼んでるんでしょう 「イテレータが指してるコンテナ」ですか?
イテレータが指してるコンテナ? vector<int>::iterator it; だと vectorが「イテランド」になんの?
例えば vector<int> v; vector<int>::iterator it = v.begin(); なら、itはvのイテレータで、vはitのイテランドです
iterateeとか言ってみる。
Pythonではiterable
iterable はまんまイテレータ(とみなせるもの)。
itのコンテナ 程度にしか言わないな
イテランドがまあ、何を指している言葉かは オペレータ⇔オペランド からの類推でわかるけどさ。 それより世間一般ではイテレータなんだろうが、 俺はついついイタレータと読み書きしてしまう今日この頃。
いてまうどー
とりあえず、イテランドがあんまり一般的な言葉じゃないことはよくわかりました 内輪以外では使うのを控えることにします ありがとうございました
あんまりという表現なのか・・・w
つうかどこでその言葉を習ったんだろ
イテランドでぐぐるとこのスレが引っかかるなw
イテランドたんのアニメ化が決定したそうです。
とある言語の被反復構造(イテランド)
パパ〜遊園地いきたーい よーし家族みんなでイテランドにでもいくか〜
井手ランド
とある要素の列挙目録(イテレータ)
イテランドたんの要素数は103000ですね、わかります。
変数 X が std::list 型で変数 I がその reverse_iterator だとすると X.erase( I.base() ); で I が示す要素の隣を消去するので I はまだ使えますよね。 VC8 で I を使うと assert で止まるんですけど。
その1行だけ示されてもなあ。
デバッガで追えばいいじゃん……
string strに入っている文字列のi番目から後ろをstr2に代入するにはどうすればいいですか?
str2 = str.substr(i);
substr
595です。ありがとうございました。あとstringを==で比較するときに小文字と大文字を区別しな方法はありますか? 一度変換しないとだめでしょうか?
stringはそもそも「大文字と小文字」っていう概念が無いと思う
大文字だの小文字だのは真面目にやり出すと大変だぞ ロケールの問題とか
>>598 std::list の reverse_iterator の場合は1つ後の要素を消去したとき無効になるんですね。
stringは複雑なんですね・・・わかりました
複雑なのはstringではなく、真の国際化です
"ガ"と"ガ"を==で比較してtrueにできないからstd::stringはクソ
CLでいうところのequalpを手前で実装しろクソ
@と`を同じ文字と解釈するべき環境とかあるからな
7bit ASCII内での大文字小文字無視なら、char_traits自作でやる実装を何かの本で見た。
typedef pair<double,string> HOGE; void func(??){ HOGE p; p.first = data; p.second = chordname; pairs.push_back(p); } int main(){ deque<HOGE> pairs; for(){ func(); } } mainで作ったdequeにfunc関数で値を入れたいんですがどうしたらいいですか? もちろんmainのスコープを抜けない限り、dequeが初期化されないようにしたいです。
引数
引数なのはわかるんですが・・・ void func(deque<HOGE> &pairs){ } main(){ func(pairs); } こうですかね?
>もちろんmainのスコープを抜けない限り、dequeが初期化されないようにしたいです。 むちゃくちゃだ。
えっと具体的にどうおかしいですか?
頭がおかしい
mainのスコープを抜ける=プログラムが終わる プログラムが終わった後にdequeが初期化されるって、 atexit内で初期化したいのか
えっとそれで611で大丈夫ですかね?
private な vector<int> hoge を外部から走査して数値を得たい const int *mage = &hoge; のような方法でするのかな?と思ったんですが セオリーな方法はどんな書き方なんでしょうか
参照せずに値じゃね?
620 :
618 :2008/11/23(日) 00:45:59
いやいまいちお前がなにいってんのかわかんないけど
hogeをスキャンして数値を返すメソッドを公開すればいいじゃない
プレイベートなデータなので、捜査には礼状が必要です。
vectorの中身は連続性が保証されている、
つまりprivateなvectorの、先頭アドレスを返すような関数作って
それをconst int * で受け取り(もちろんサイズも)、
そのconst int * を走査するのかな?と思ったけど
書き方がわかんないから
>>618 になってしまった
ゴメンナサイ(´・ω・`)
beginとendのペアを返す
>>621 スキャンって・・・?
丸ごとコピーしてそれを返す?
内部でiterator保持して呼び出す毎に進める?
現場の人じゃないから、その手の語彙力ないんだわ(´・ω・`)
ちなみに具体的にはintではなく
x,y座標が入ってるpair<int,int>で
これを取得してGUIでリアルタイムに線を引きたい
という状況です
現場の人とか関係ねーw
>>618 の走査 ==
>>621 のスキャン
だろOKJK
それから情報後出しって嫌われるの知らないかね
いいから黙ってソースコードべたっと貼れ
では俺はコールバックを提案しよう。
629 :
618 :2008/11/23(日) 02:19:18
>>627 GUIライブラリ使ってる上に携帯厨なんです(ノ∀`)
typedef std::pair<int,int> Pos
class Hoge{
public:
const Pos *getPosArray(int *arraySize);
private:
std::vector<Pos> p;
};
const Pos *Hoge::getPosArray(int *arraySize){
*arraySize = p.size();
return *arraySize ? &p[0] : 0;
}
こうしてみた
コーディングスタイル云々は勘弁してつかーさい
const std::vector<Pos>& ppp() const { return p; } でいいじゃん
631 :
デフォルトの名無しさん :2008/11/23(日) 14:43:29
int function(string &buff){ } main(){ string buff: function(buff); } mainで宣言したstringに関数で値を入れるには、これであってます?
ありがとうございます。 functionでの代入時は buff ="mozi"; みたいな感じでいいですか?
俺ルールだと、関数で値を入れる場合はポインタ渡しにして、 単に値を渡すだけなら参照にしてるな。
>>633 それでいいよ。
値を渡すだけでも、返してもらうときでも参照でいいよ。
const のあるなしで区別すればOK
>>634 M$ なんかが当初そういう方針だった気がするな。
NULL チェックが必要になるから個人的には微妙なんだが・・・。
>>635 賛成。
それとは別に、俺は std::string 程度なら値を返すようにしたい。
function().length() したいだけだったり、function() で代入したものを他の関数に渡したいだけだったりした時に、わざわざローカル変数を作らなければならないから。
また、ローカル変数に代入すべき場合のうちで初期化後に変更しないものに const を付けられなくなるから。
オーバーロードして両方のバージョンを用意すればいいだけだけど。
>>635 こうしろと?
int& function(string &buff){
>>635 int function(int&, double& )とかした場合
function( 1, 0.1) は使えないだろ
こんな使い方禁止?
>>640 直前のカキコとか見れよ。
引数で値を返してもらいたいとき、constなしの参照つかえって意味だから、
そういう使い方は意味ないだろ。
642 :
デフォルトの名無しさん :2008/11/24(月) 19:24:39
istreamから数バイトずつ読み取って意味解釈していくような プログラムを作っているのですが、 istream input; short header1; input.read(&header1, sizeof(header1)); short header2; input.read(&header2, sizeof(header2)); こんな感じでしか書けないのでしょうか? short header1 = input.read(sizeof(header1)); short header2 = input.read(sizeof(header2)); などと書ければよいのですが・・
>>642 read<short>(input) とかいう関数でも作れば良いんじゃない?
>>642 short header1, header2;
if(input >> header1 >> header2) {
// ...
}
646 :
642 :2008/11/25(火) 01:57:17
>>643 こんなのを作ってみました。
template<class T>
std::istream& read(std::istream& is, T& data)
{
return is.read(reinterpret_cast<char*>(&data), sizeof(T));
}
>>644 それって、inputが文字列なら良いですが、
バイナリ読みしたい場合はダメですよね?
647 :
デフォルトの名無しさん :2008/11/25(火) 16:50:03
vectorのイテレータは足し算ができるのに、listのイテレータではできないんですね。 listで添え字アクセスのようなことをやる場合は、 list<int>::iterator it = list.begin(); for(size_t i= 0; i< index; i++ ) it++; みたいなことをやらないといけないの? 挿入とか削除とかが多い配列なのでvectorよりlistを使った方がいいんですが、 indexを使ったアクセスも多いので、なんかブサイクですね。 いい方法ないですか?
>>647 コンテナの種類とランダムアクセスイテレータに関して
も少し理解を深めといた方が。
>>648 ランダムアクセスをしたいならvectorを使うべきだと?
一般論ではそうでしょう。
しかし、
vectorの場合、挿入・削除におけるコストは配列要素の数が増えるに従って等差級数的に増大します。
listの場合は配列要素の数にかかわらずコストは一定です。
だから、配列要素の数と、挿入・削除・ランダムアクセスの頻度を考えて、
処理速度的に最適なものを選びたいと思っています。
それで私のケースではvectorよりlistが妥当だと判断した訳ですが、ソースの記述がブサイクだと言ったまでです。
>>649 listの要素の入れ替えをしたくはないのです。
>>650 つdeque
ランダムアクセスできて挿入も速い
>>651 私のケースでは、挿入・削除を行う位置は先頭・末尾でないことが圧倒的に多いのです。
>>652 dequeは途中の挿入も(そこそこ)速いんだよ。
dequeの仕様を満たそうとすると、どうしてもそういう実装になる。
>>650 要件がいまいちつかめないので何ともいえないけど、
規格を眺めてlistが最適だと思うなら仕方がないんじゃない?
listはランダムアクセス出来ないしね。
でも、std::advanceの認識からしてSTLの理解甘そうだし、もう一度規格眺めることをおすすめするよ
>>652 要素の連続性がいらないがアクセスがランダム性高い状態ならdequeにしとけ
周りがアドバイスしても結局自分の方法に固執するんじゃ 何言っても意味ないよ そういうのはほっとくに限る
挿入/削除が多いならリストを使うべきだろ ときどきランダムアクセスが必要ならstd::advanceで
advanceを思いっきり勘違いしてる節があるよね
>>655 配列要素数が数万個以下の場合は、dequeよりむしろvectorの方が速かった。
VS2005でコンパイルした場合だけど。
用途によっては挿入/削除/ランダムアクセスが全部O(log n)のデータ構造も検討するといいかもな STLにはないけど
>>647 より後の返答カキコ 本当に
>>647 なのか?
おまえら、誰かに釣られてないか?
IDのない板って、なりすまし可能だからな
質問に答えてるだけなんだから、
>>647 と
>>650 が同一人物であろうとなかろうと何も関係ない
釣りだったとしても痛くも痒くもない
std::vector<要素 *>
skip listか んなもんわざわざ使うなら普通にlistでもいいと思うけどな
>>647 はlistを使うのを前提として質問していて
listの代わりに何が良いかは質問してないようによめるのだが
>>666 setにはイテレータを指定するinsertと指定しないinsertがあるよ
vectorにそのままクラスを入れるとコピーコンストラクタを何度も呼び出してるようなので クラスのポインタを入れて使おうかと思ってるのですが 何か注意しなければ行けない点はありますか?
あります vectorから取り除いたときのdeleteし忘れ
FUGAはduobleとstringのpairです multiset<FUGA> huga; にいくつかデータが入っています。これからある文字列(stiring)の数をカウントしたいんですがどうすればいいでしょうか? count関数がありますけど使い方が・・・ huga.count("hogehoge");みたいな感じで使いたいんです
678 :
デフォルトの名無しさん :2008/11/26(水) 11:06:22
KOUZOUTAI data[100]; partial_sort( data, data + 10 ,data+100, Sortpred1) ってできますけど vector<KOUZOUTAI> data(size); partial_sort( data.begin(), data + 10 ,data.end(), Sortpred1) ができません。第2引数の書き方が問題だと思うんですが、どう書けばいいでしょうか?
const_iterator を iterator に変換するために distance() と advance() を使う方法が Effective STL にありますが、この方法はランダムアクセス反復子でないと定数時間で 変換できません。 std::set の const_iterator を定数時間で iterator に変換する方法はあるでしょうか?
typedef std::set<A,B> C std::set<C::const_iterator,C::iterator> を作って変換しろ
>>681 std::set, std::map の検索は普通の実装で対数時間
*reinterpret_cast<std::set<A>::iterator*>(&cit) 大体の実装なら通るよ 細かいこと気にすんなってwwwww
対数時間なら別にいいんじゃね
>>680 とりあえず何のためにそんな変換をする破目になったのか教えてくれまいか?
>>680 定数時間にこだわるんならどうぞ
std::tr1::unordered_map<C::const_iterator, C::iterator>
vector<vector<T> > WArray; WArray warr (100, vector<T>(10)); T型の2次元配列を作る場合、このようにすることが多いのだけど 全体のデータサイズは、size_of()関数で取得できるけど、配列の行数と列数のサイズ を知りたい場合、方法は無いのでしょうか?
> 全体のデータサイズは、size_of()関数で取得できるけど、 できるか?
>>688 >>687 です
ごめんなさい、間違えました
size_t size = warr.size();
こうでしたね(^^;
いや、それ全体じゃないから。
691 :
デフォルトの名無しさん :2008/11/30(日) 17:38:11
detours.lib(detours.obj) : warning LNK4099: PDB 'detours.pdbの解決方ありますか?
マルチ市ね
693 :
デフォルトの名無しさん :2008/11/30(日) 17:45:42
detours.lib(detours.obj) : warning LNK4099: PDB 'detours.pdb' が 'C:\Program Files\Microsoft DirectX 9.0 SDK (Summer 2004)\Lib\detours.lib'に見つかりません。デバッグ情報がないものとして、オブジェクトにリンクします。これの意味と解決方教えてください
さっさとしね
大体わかるけどマルチ野郎には絶対教えない
こんなファイルがあって、 -- a foo FOO a fooz FOOZ a foz FOZ b bar BAR b baar BAAR -- その場合、こんな関係を現わしているんだけど、 -- a-+-foo +-fooz +-foz b-+-bar +-baar -- どんなデータ構造にするのが手頃か相談に乗ってくれまいか。
何やりたいかによるだろうが、単に vector vector ではだめなの?
aやbがなければvector<vector<pair<string, string>>>でいけるかな。問題は、 aかb(か他の何か)を選択した後に、fooなりなんなりを選択するってユーザインターフェースがあることなんだ。 おまけに、fooを選択したときの出力はFOO(単純に大文字って事じゃないよ)でないといけないわけで。
mapでいいだろ
楽しようと思えばmap<string,map<string, string> >かなぁ
>>698 なんかよくわからんが、vector<pair<>> を含む class を作れば
いいのかな。出力もメンバ関数でもできるし。
multimap<string,pair<string,string>>とかかな・・・ S式にした場合に(("a" ("foo" . "FOO") ("fooz" . "FOOZ")) ("b" ("bar" . "BAR") ("baar" . "BAAR"))) みたいなのを表現したいってことなら
struct Entry { string type, id, name; bool operator<(const Entry &a) const { return type < a.type; } }; multiset<Entry> entries; でequal_range使わせるかな
定数時間でa->foo->FOOと引く必要あるなら、map二段構えが一番楽じゃね。
レスありがと。 なるほど、色々手はありそうだね。 ちょっとmultimapとmultisetを調べて、どれにするか決めるよ。 # 昨夜のうちに決めようと思ったのに眠りこけていたのは内緒w
706 :
デフォルトの名無しさん :2008/12/04(木) 20:31:19
vectorを配列っぽく使ってるんですが、 eraseに渡す値はイテレータじゃなきゃ駄目なんでしょうか? vec.erase(vec[5]) vec[5].erase() みたいなことはできませんか?
begin()+5
708 :
706 :2008/12/04(木) 20:36:56
おおー。感動です。ありがとうございました。
まあ使い辛いとは思うがな・・・。
関数の戻り値を直接 + とか . で使えることを初めて知ったときは感動したな。 とどうでもいい回顧
. はともかく + は・・・。 数学的に、単独の方が違和感あると思われ。
右辺値やな
for_eachの使い方を知ったときは感動したけどやっぱり使いづらい
lambda なしに for_each だけあってもね・・・。
range adapterも欲しいナ
rangeベースのforとアルゴリズムとlambdaだけでもwktkが止まらない
717 :
デフォルトの名無しさん :2008/12/06(土) 15:46:46
deque<string> buff; にpusu_back()は定数時間ですか?それと buff[0]みたいなアクセスはありですか?
「deque push_back 定数時間」でググれば、皆同じことを言っているし、 buff[0]みたいなアクセスが「あり」かどうかは自分で書いてコンパイルすればわかると思うんだが、 何故こういう質問が書き込まれるんだろう。 あと、「みたいな」っていうのがよくわからん。 それ自体だけでなく「それとはちょっと違う何らかのアクセス方法」も込みで訊ねてるのなら、 その内容次第で返答は変わるかもしれないから、もうちょっと具体的に書くべき。 もし、自分の表現に対する自信の無さゆえに「ぼかし」を加えたに過ぎないなら、 そういうのはただ単に答えにくくなるだけだから、やめたほうがいい。 答を書かないことも含めて、親切すぎて逆切れされる可能性大だな、このレス。
長々となに書いてんだろ PC触りすぎて酸素欠乏症なのかな
std::dequeはrandom access containerとback insertion sequenceの要件を満たしているので operator[]によるrandom accessが可能かつ、 push_backによる要素追加は償却で定数時間であることが保証されています
>>720 > 長々となに書いてんだろ
馬鹿が読むと煽りたくなるアドバイスじゃない?
むしろpush_backが償却定数時間よりひどいコンテナなんて無いだろw
これらの操作を提供するための条件として規定されてるからね。
set とかは insert だしな。
726 :
デフォルトの名無しさん :2008/12/09(火) 14:44:05
vectorの2次元配列はどうすればいいんですか? 2次元目も動的にしたいんです
vector<vector<int> > v;
ありがとっ
これって問題ある? class CVector { vector<int> A; } vector<CVector> B; CVector.A.resize(10); B.resize(10);
class CVector { vector<int> A; }←セミコロンがない vector<CVector> B; CVector.A.resize(10);←クラス内の動的メンバへのアクセス方法がおかしい B.resize(10);
あそうか、こうしないとインスタンスが作れなかった class CVectorSub { public: vector<int> A; }; class CVectorMain { public: vector<CVector> B; }; class C { public: CVectorSub vSub; CVectorMain vMain; void Resize() { vSub.resize(10); vMain.resize(10); } };
やばい 2次元配列じゃなくなってる 意味ねぇ
あ!わかったthx! class CVectorSub { public: vector<int> A; }; class C { public: CVectorSub vSub; vector<CVectorSub> vMain; void Resize() { vSub.A,resize(100); vMain.resize(10); } };
うわ・・・これダメだ
>>733 vSubを操作してもvMainに影響しないし、vMainを操作してもvSubには影響しない。
わかってるならいいんだけど。
エスパーすると
vector<vector<int> > vec;
vec.resize(10);
for(int i=0; i!=vec.size(); ++i)
{
vec[i].resize(10);
}
なんじゃないかと。
違ったら無視して。
いやそれです。ありがとう それだと全部同じ配列数になるのかと思ってしまった。 vec[0].resize(10); vec[5].resize(20); こう出来たんだ。 暴れてしまった・・・すまんTHX
2次元配列の初期化とポインタの使い方あってますか? vector<vector<int>> vec(5, vector<int>(100, 0)); vector<vector<int>>* pVec = vec; pVec[3]->resize(200); pVec[3][180] = 12345;
いいえ。
>>737 > vector<vector<int>>
まずこれがだめ。正しくは
vector<vector<int> >
2行目はコンパイル通らない。
3行目と4行目も意味がめちゃくちゃ。
ポインタをインデクサで参照して実態をアロー演算子で参照してるがな 大体はそんな流れでいいと思うが後は実際にビルドしてみるよろし つーか何でポインタが出てくんの?w
何がしたいかよく分からない例だが そのまま直すとこんな感じか vector< vector<int> > vec(5, vector<int>(100, 0)); vector< vector<int> > *pVec = &vec; (*pVec)[3].resize( 200 ); (*pVec)[3][180] = 12345; しかしvectorに直接vector入れたらりサイズのコストがやばそうだな^^;
ありがと。 本2冊読んで> >の間のスペースがわからないのがやばい vector<vector<int> > vint; vector<vector<char> > vchar; ごめん↑を分岐なしで使えるようにするためにポインタに入れたかったんだけど vector<vector>* pvec = char; ここの書き方がわからないお願い!
そこでテンプレート関数の出番ですよ main() { vector< vector<int> > vint; vector< vector<char> > vchar; if(〜〜〜) test(vint); else test(vchar); } templete<class T> test(T &vector) { vector[3].resize(200); vector[3][180] = 12345; } 適当に書いたから間違ってるかも分からん
>>742 共通のクラスを継承してない限り、型の違いをポインタでは吸収できない。
なので
>>743 の方法になる。
いや何を書いてあるのかがわからなかった コンテナの前にテンプレートを勉強してくる ありがと、まじありがとっ
今更勉強するより0xまで待った方がいいかもなー
それは0x完全対応コンパイラを待ってから勉強するってこと? あ、老後の楽しみか
なに微妙に興奮してんのw
749 :
デフォルトの名無しさん :2008/12/12(金) 07:10:55
上級者すぐるw
751 :
デフォルトの名無しさん :2008/12/13(土) 01:33:45
[SourceForge.net: Project File Releases: STLport] STLport STLport-5.2.1 released (Wed, 10 Dec 2008 10:50:47 GMT) (2008-12-10 19:50)
0x ってもうあと一年しか残ってないんだ
もしかして 09 でなくて 0xa だったりして
754 :
デフォルトの名無しさん :2008/12/13(土) 12:24:32
すみません、c++のカスタムアロケータでの質問なんですが カスタムアロケータとしてmy_allocatorを作り、 それを指定したbasic_stringを typedef basic_string<char, char_traits<char>, my_allocator<char> > my_string; と定義しました。 それでやりたいことなんですが my_string ms = "ms test"; std::string ss = "ss test"; ms = ss; と、アロケータの違うコンテナ同士で代入をしたいのです。 今はとりあえず my_string ms = "ms est"; std::string ss = "ss test"; ms = ss.c_str(); としてますが、ちょっと不恰好で気になってしまいます。 なにかスマートな方法はありますでしょうか?
assert(ms.size() >= ss.size()); std::copy(ss.begin(), ss.end(), ms.begin());
おぉなるほど、イテレータを使えばいいんですね。 ありがとうございます。参考にして作ってみます。
ss.assign(ms.begin(), ms.end());
STLの仕様とかよく理解できてないから根本的におかしいかもだけど、 map< HWND, LPFUNC >みたいな使い方ってダメなんでしょうか。 (LPFUNCは関数へのポインタ型) コンパイルは通るんですが、insert()すると必ず失敗してしまいます。
失敗ってどんな?
760 :
758 :2008/12/15(月) 19:15:39
>>759 insert()したときの戻り値の.secondが必ずfalseになる
エラーが起きる最小限のソース貼ってみ
762 :
758 :2008/12/15(月) 21:15:36
一時オブジェクト?
765 :
758 :2008/12/15(月) 22:46:02
ローカルのものをmapにはinsert出来ないということですか?
764が言ってるのは、 自分でinsertを呼ぶよりも前に、WndProcが呼ばれて LPFUNC lpfn = hoge[ hWnd ]; で、hWndに対応する関数ポインタがヌルとして登録されてしまうってことでしょ
767 :
758 :2008/12/15(月) 23:11:12
なるほどやはり詳細な仕様を知らないで使うとへんなとこでバグになりますねー。 つまり、findでイテレータを探して、そのイテレータの指す先が有効だった場合にlpfnに代入すればいいということでしょうか。
>>765 つ
// LPFUNC lpfn = hoge[ hWnd ];
// if ( lpfn ) return ( lpfn )( hWnd, msg, wParam, lParam ) ? 0 : E_FAIL;
これでinsertは成功
わざわざエラー検査する必要ないのでは? hoge[ hWnd ]=lpfn; でいいじゃない
770 :
758 :2008/12/15(月) 23:25:16
STLというよりWindowsAPI、ウィンドウ生成周りの勉強だと思う
772 :
758 :2008/12/16(火) 17:26:11
CreateWindowが幾つかメッセージ送るのは知ってたんですが、 find()使わないでoperator[]使うと存在しないキーを参照しようとしたときに、 対応するキーが作られるのを知らなかったので、そこらへんの勉強をという意味です。
773 :
デフォルトの名無しさん :2008/12/17(水) 17:11:03
vector<int> vec; vec.push_back(3, 10); というふうに書けないのはなぜですか? Insertで配列が動的に増えないで溢れるということは、これができないと、 vec.push_back(10); vec.push_back(10); vec.push_back(10); と3行分の処理を書かないといけないとおもうのですが、他にいい方法はありませんか?
resizeを使え
vec.insert(vec.end(), 3, 10); でよろしい
fill_n(vec.begin(), 3, 10);
>>775 それだとendを指定しておけば配列が3つ増えてくれるんですか?
endじゃなくて中間を指定すると要素は3つずれて配列数は減らないで後ろの3要素が消滅しませんか?
3つずれて配列数は 増えないで 後ろの3要素が消滅 の間違えです
増えます。 しません。
>>776 これがfill_n一行でできるということでしょうか?
deque<int> deq;
deq.resize((deq.size()-1)+3;
deq.insert(deq.begin(), 3, 10);
>>780 まじですか?本のどこを読み間違えたんだろう・・・
すいませんでした。
解決しましたが、書きなおさせてください deque<int> deq; deq.resize((deq.size()-1)+3); deq.push_front(10); deq.push_front(10); deq.push_front(10); でした。もっと勉強しますありがとうございました。
dequeでどんどん要素を追加していく場合はスタックにつまれるんですか?またはヒープ領域ですか?
ヒープ
フリーストア
>>786 ありがとうございます。
どんどん増やしていってもう領域が確保できないってなったらなんかエラーがかえってきますか?
>>788 帰ってくるかもしれないし、帰ってこないかもしれません。環境によっても振る舞いが変わりますので諦めてください。
概念的にはstd::bad_allocが投げられることになっている。
mapと(STLportの)unordered_mapの簡単な速度比較ベンチ書いて試してみたんだけど どんな条件にしてもunordered_mapの方が速くなる。 一般的に言ってmapには自動的に順序付けされる以外の使いどころってある? mapの方が速くなるようなコードや環境って割りとあるもの?
>>788-790 領域が確保できないときはデフォルトのアロケータを使ってるなら std::bad_alloc が
投げられることになる。これは規格で決められていること。
「どんどん増やしていって」ということだと max_size() を超えたときの std::length_error が
先に飛んでくるかもしれない。
>>791 スピードについてはハッシュの使える unordered_map より速くなることは少ないだろうね。
そう言えるからこそ新しく規格に盛り込まれたんだろうし。
ただしハッシュ関数が適切でないときに逆転する可能性は考えられると思う。
>>791 順番に並べるという制約が付いたものとそうでないものを比べれば
余計な制約のない方が一般に高速に実装できるというのは当然じゃないかと思う
795 :
デフォルトの名無しさん :2008/12/19(金) 20:39:06
vec.erase(vec[i], vec[i+2]); これエラーになるんですが、 この場合のイテレータってどう書けばいいんですか?
796 :
デフォルトの名無しさん :2008/12/19(金) 21:01:07
すいません解決しました vec.begin+i
>>792 MFC 使ってると代わりに CMemoryException 例外が投げられたりする。
一度これでハマった。
798 :
791 :2008/12/19(金) 21:36:00
>>793 なるほど、ハッシュ関数の質が効率に強く影響するのが特性であると。
整数のような単純なkeyではデメリットが表面化しないということか。
>>794 そうかもしれないけど、ハッシュコンテナが「一芸に秀でる」ような
アルゴリズムだったら一概に言えないかと思って。
元々はツリーの方が挿入・検索・削除の混在に強いと聞いたので試してみたら
それほどでもなかったという話だけど。
ハッシュがデメリットになるっつーと、 ハッシュ値のとりうる範囲がやたら広いときくらいか?
同じキーのデータが大量に入る可能性がある時とか
>798 キーの衝突が発生しない限り、挿入、検索、削除のいずれもハッシュの方が高速だと思うんだが。O(1) vs O(log n) だよな?
メモリ消費量なんつー尺度もありましてね
「キーの衝突が発生しない限り」はな 実際にはその保証が難しい場合もある そうすると最悪O(n)になっちゃうからリアルタイム性が求められる場合とかは使えない そういうときはどんなに最悪でもO(logn)が保証される(適切に作られた)ツリーコンテナの方がいい まあフツーのPCアプリなら何も考えずにハッシュコンテナでいいことが多いけど 常にそれでいいと考えてると落とし穴に嵌ることもあるという話だと思う
hashtree
>>798 テストコードを晒してくれ。
順序性が必要な時でも unordered_map の方が早かったんだよな?
itor++ とかするコードでだよな?
知らないみんなの勉強になるから頼む。
>>796 括弧がない
vec.begin()+i
end()の方はどうなってる?
yahohho- yahhohho- no-bura yahho-
いや普通に疑問だろ
おしりのあながかゆい
>>811 虫がいるんだろう。
ポキールあげるから明日持って来なさい。
ポキール懐かしい。 最近も使ってるのかな。
814 :
デフォルトの名無しさん :2008/12/23(火) 07:52:43
deque< vector<int> > deq; deq.push_front(vector<int>) この型は演算子として使用できませんとでます。なんでですか?
型名を関数の引数にはできない。
thx deque< vector<int> > deq; vector<int> vec; deq.push_front(vec); これで動いた
>>814 deq.push_front(vector<int>());
これならOK
816の場合 同じインスタンスであるvecを配列に追加していったら 参照したときに全配列全部同じ値を共有している状態だと思うんだけど 実際中を見るとvector<int>が複数出来てた。 このときdeqから参照しないでvecを見るとどのdeqのvecが入ってるの?
>>818 コピーコンストラクタとか代入演算子って知ってる?
std::deque<std::vector<int> > deq; std::vector<int> vec; deq.push_front(vec); deq.push_front(vec); deq.push_front(vec); deq[0].resize(10); deq[1].resize(20); deq[2].resize(30); std::cout << deq[0].size() << ' ' << deq[1].size() << ' ' << deq[2].size() << std::endl; つまり全部別物。
それで、 std::vector<int> vec; は一つじゃないですか。 deq[].sizeで値が変わるのは、まあわかってないのですが、置いといて、 vec.sizeとしたときに、どのdeqのなにが返るのか あ、vecのサイズは0か。 vecが合計4つ存在してることになるのか。コピーコンストラクタがやっとわかった気がする ありがとう!
#if defined(_CONCEPT_CHECK_H) || defined(__CONCEPT_CHECKS_H) || defined(_STLPORT_VERSION) // SGI, STLPort, etc //_Tp* _M_start; //_Tp* _M_finish; //_Tp* _M_end_of_storage; #elif defined(_RWSTD_VER) /*&& !defined(_STLPORT_VERSION)*/ // Rougue Wave //size_type __buffer_size; //iterator __start; //iterator __finish; # define _M_start __start # define _M_finish __finish #elif defined(_STD_BEGIN) // Dinkumware? //pointer _Myfirst; // pointer to beginning of array //pointer _Mylast; // pointer to current end of sequence //pointer _Myend; // pointer to end of array # define _M_start _Myfirst # define _M_finish _Mylast #else # error unknown STL vendor #endif #if !defined(_GLIBCXX_STD) # define _M_impl (*this) #endif
class vectbuffer: public std::vector<char> { public: void unintialize_force_resize(size_type size) { assert(size <= capacity()); _M_impl._M_finish = _M_impl._M_start + size; } }; #undef _M_impl #undef _M_start #undef _M_finish これ、動かないメジャーな実装あるかな? 仕様外、保証外だというのは承知の上で ファイルやネットワークからの読み込みバッファや ファイル圧縮等の出力先なんかに使おうかと考えたんだけど。 まあresize()使うのが正しい方法だとは思うけどね。 今までreserve()だけしてバッファに使ってた 俺みたいな悪い奴はそんなに居ないか。
#define reserve resizeはだめ?
そこまでやるなら普通にバッファクラス作れと思わんでもない 大体初期化オーバーヘッド自体どうってことないしresizeでいいだろ
その初期化オーバーヘッドが問題になってるのかもしれない
newしてauto_ptrにかち込むだけでは物足りないのか
わざわざvectorを継承する意味がわかんね
>>825 作ったら作ったで車輪の再発明と言い出す奴が必ずいるという事実
コンテナって継承向きじゃないよな確か 仮想デストラクタになってないし
>>827 配列は(ry
まあ、例外安全とか単なるミスや検証の手間を防ぐ意味でも
vector<char>をバッファにというのは悪い考えではないでしょ。
ただ、それをresize()して使う場合の「無駄な初期化」をどう見るかと。
vector<int> vec; vec.resize(INT_MAX); このコンテナにデータを効率よくいれるにはどう書けばいいですか? int data[INT_MAX]; for(int i=0; i<INT_MAX; i++) { vec[i] = data[i]; } これめちゃくちゃ遅いんですけど他に手はありますか?
std::copy
そんなにメモリあるのか?
>>832 assign() するとか。その場合は resize() 要らない。
ヒント 64bit環境でも普通intは32bit sizeof(int[INT_MAX])は8G
それがvecとdataで16GiB。そんだけメモリ積んでるって、先ずないと思うのだが。
アドレス空間は足りる(実行は出来る)ってことよ。 もちろん遅くて使い物にならないというのは同意。
>>839 アドレス空間が足りていたとしても、スタックエリアが 8GB とかは絶対無理かと。
>>832 INT_MAXはおいとくとして
vec.reserve(INT_MAX);
for(int i=0; i<INT_MAX; i++)
{
vec.push_back(data[i]);
}
でいいんじゃない?
わざわざループしなくてもassign()で一発じゃん
あとは、vectorはメモリの連続が保証されてるんだから memcpyあるいは環境依存で最も高速なメモリコピー手法を使うとか。
もうループはcode smellだと思ってよさそうだな
smellどころかループが時間食うなんて確定的に明らか
そういやノンスメルのCM見なくなったな。キムコも。
64ビット環境なら 8GB 使うくらいはあり得る話だが、それが遅いのは仕方が無い。 型が int だから memcpy でコピーすりゃいいが、それでも遅いのは遅いだろうな。 ただ、data はどうやって作ってんの? ってのが気になるな。 スタックに 8GB は無理だし、 静的に 8GB も取ってるとしてもどうなのよって感じだ。
std::vector::resize の現在の仕様はウンコで、 サイズだけ指定した場合は POD 型だろうがメモリがデフォルトコンストラクタで得られる値で初期化されてしまう。 C++0x では改善されているようだが、現状では resize するだけでも初期化ルーチンが走ってしまい、 さらにその後 data のコピーが走ることになる。 コピーするだけなら、resize じゃなくて assign を使うこった。
こんなの普通ファイル使うで。 てか質問者は大きいエリアという意味で、軽い気持ちでINT_MAXって 書いてしまっただけじゃないかと思うんだ。そんな端数必要な状況ってそうそうある?
>>849 > C++0x では改善されている
詳しく。
イテレーターが未初期化である場合に入れる、 ポインタに入れるNULLみたいな値ってありましたっけ?
ありません。 というか、イテレータってなにかわかってんの。
イテレータが「初期化」されているかどうかを判別する必要が あるなら、それはプログラムがおかしい。コードを見直せ
処理したかどうか判定したいなら、コンテナのend()の戻り値でも入れといて後で比較すれ
例外発行しましょうね
>>851 1引数の resize が追加された。
現行の規格では resize は2引数で、
第2引数は const T& value = T() になってる。
だから、メモリが確保された場合、
そのメモリは T() でコピーコンストラクトされる。
>>857 ありがとう。
しかし、この変更は「改善」と言ってしまっていいんだろうか?
C++ 2003 での POD のゼロ初期化に依存していたコードが静かに壊れることに
なりそうだ。
>>823 的な動作(reserveも含む)が仕様に含まれるということかね。
>>858 の言うように、同じ名前じゃ互換性の問題が出る可能性もあるだろうに。
んーよく見たら "default constructed element" で埋めるって書いてあるな。 "default constructed" が "default initialized" という意味なら改良されてると読めるが、 規格中のほかの箇所では T() を指して "default constructed" と書いている箇所もある。 実は記述が紛らわしいだけで、 C++ 2003 と変わってないんじゃないか?
C++0xドラフト(N2798) 23.2.6.2より requires AllocatableElement<Alloc, T> void resize(size_type sz); Effects: If sz < size(), equivalent to erase(begin() + sz, end());. If size() < sz, appends sz - size() default constructed elements to the sequence. あれ?同じじゃね?
default construct って、POD 型の場合は何もしないんじゃないの?
>>863 default initialize ならそのとおり。でも default construct は T() のことかもしれない。
T() だとすると value initialize となって、 POD の場合は zero initialize になる。
default constructという用語は今の規格には存在しないし C++0xの最新ドラフトでも説明なしに使われてる(これはまずくないか) default initializedは今の規格とC++0xで変わってて 今の規格では非PODはゼロ初期化することになってるが C++0xの最新ドラフトでは非クラスは何もしないとなってる
またアキラ君か・・・
868 :
デフォルトの名無しさん :2008/12/30(火) 15:45:23
こんにちは。逆順にソートされている配列に対して、 lower_bound(のようなもの)を適用することはできますか? 配列の代わりにvector<int>にしてreverse_iteratorを使えばよいということは分かるのですが、 配列のままで可能であればそれが良いなと思っています。お願いします。
int a[N]; int* p = std::lower_bound(a, a + N, std::greater<int>());
870 :
869 :2008/12/30(火) 16:16:30
違うわ、1個引数抜けた std::lower_bound(a, a + N, value, std::greater<int>());
871 :
868 :2008/12/30(火) 16:19:13
>>869 さん
そうすれば良かったのですか、ありがとうございます。
872 :
デフォルトの名無しさん :2008/12/31(水) 15:40:29
vector< vector<int> > m_vec; size = 10; m_vec.resize(size); for(int i=0; i<= size; i++){ m_vec[i].resize(10000, 0); } このあと、 for(int i=0; i<= size; i++){ m_vec[i].resize(10, 0); } こうしたんですが、メモリの使用量が減りません。 繰り返すたびにどんどん増えていくんです。 どうすれば解放できるんでしょうか?
別にvector用意してそっちに値コピーした後swapする
>>872 vector<int>().swap(m_vec[i]); をsize分繰り返す
待てよ vector<vector<int> >().swap(m_vec) なら一発で行けるかも
やってみた int main() { std::vector<std::vector<int> > m_vec(10, std::vector<int>()); for(int i = 0; i < 10; i++) m_vec[i].resize(1000000); std::getchar(); std::vector<std::vector<int> >().swap(m_vec); std::getchar(); } 一度目のgetchar() (タスクマネージャから) 40652K 二度目のgetchar() (タスクマネージャから) 1552K うまく動いているようだ
ありがとうございます!今まで小さい配列しか使ってなかったのでメモリが解放されないとは知りませんでした。 swapでなぜ解放されるかさっぱりわからないので勉強してきます。 vector< vector<int> >* m_vec; m_vec = new vector< vector<int> >; delete m_vec; もしこうするとしたら、 *m_vec[i].resize(10000, 0); 2番目の引数がintからvector<_Ty>に変換できませんとエラーが出るのですが、ここはどう書けばいいんでしょうか
>>877 だめです一部しか解放されません。
for(int i = 0; i < 10; i++)
m_vec[i].resize(1000000);
}
for(int i = 0; i < 10; i++)
vector<int>().swap(m_vec[i]);
}
これはなんのデータが残ってしまってるんでしょうか
いやその・・・解放って・・・
すいませんぜんぜん違うところをミスってました。メモリリーク地獄ですね。ありがとうございました。
>>833 vector<int> vec(1000,100);
int i[1000];
copy(vec.begin, vec.end, i);
int配列にvectorって入らないんですけど。
ここはお前の日記帳じゃねーんだ、チラシの裏にでも書いてろ、な しかし今日は元旦だ。 めでたいので特別に教えてやろう。 std::copyはSTL用のアルゴリズムなんだから、int配列には対応してなくて当然。
ポインタはランダムアクセスイテレータの要件を満たしている
>>883 > std::copyはSTL用のアルゴリズムなんだから、int配列には対応してなくて当然。
C++の特殊化を根本的に勉強し直す必要がある。
>>886 もし「特殊化」を明示的特殊化のつもりで使ったのならば、
お前も勉強しなおせ。そうではないなら失礼した。
どちらにしろ検討外れだろ。 イテレータの種類について勉強しろ、ってのが正しい。
総称型によるジェネリックプログラミングのことも忘れてはいけない
()を入れたらコンパイルできました。ありがとうございました。 int* a; a = new int[1000][10]; vector < ventor<int> > vec; copy( vec[i].begin(), ven[i].end()-1, a[0][i]); これはどうすればコンパイルできますか? 配列のバウンドが定数式ではありませんと出ちゃいます
色々ダメすぎ C++は適当に感覚でやって、なんとなく動いたらそれでいいやっつー タイプの言語じゃないぞ その調子でやってたらいつまで経っても物にならん もっと簡単な言語からはじめるか、もっと基本的で低レベルなところから、ちゃんと 理解しながら進めろ
>>890 1. a の型がおかしい
new int[1000] は、int を 1000 個分確保する事を表す。
すなわち、これは int へのポインタで受ける。
new int[1000][10]; は、int[10] の配列を 1000 個分確保する事を表す。
すなわち、これは int[10] の配列へのポインタで受ける。
従って、a の宣言は int (*a)[10]; が正しい。
10 の部分は整数定数である必要があり、
サイズを変数で指定することはできない。
2. end に対する誤解
end() - 1 なんてすんな。end() でよろしい。
copy の第2引数には、最後の要素の次の要素を与える。
そして、end() は最後の要素の次の要素を与える。
だから、end() でよろしい。
(もっとも、1 個余分に作成しているのなら話は別だが)
3. copy の第3引数にはポインタまたはイテレータを与える。
a[0][i] じゃ単なる int になる。& を付けること。
4. 配列の配列のメモリ上の配置に対する無理解
a[1000][10] は、メモリ上には以下の順番で配置される。
a[0][0], a[0][1], a[0][2], a[0][3], ..., a[0][9], a[1][0], a[1][1], ...
copy に与えるのは &a[0][i] ではなく &a[i][0] にし、i は 0 〜 999 で回す。
この理解だと vec の resize 部分も怪しい可能性もあるので見直す事。
あと、&a[i][0] は a[i] と書いても良い。
C++ で動けばいいや、だと悲惨な目にあいそうだな。 どの言語でもそうだといえばそうだが、 C++ は Java とかに 比べて安全装置少ないから危険。さらにバグではないとしても どうしようもないコード書くようになりそう。
>>893 詳しく教えていただきありがとうございます!
どうしてもint[10]の10の部分を変数にする方法はないのでしょうか
// data = 1000まで入る
// set = 10まで入る
int* a = new int[1000*10]
として、サイズだけは確保し、後からa[data][set]や、a[set][data]として自由に中身にアクセスできないんでしょうか?
vector<int> s(set);
int* a = new (*s)[data];
こうするとコンパイルは出来るのですが、vectorをべたデータにしたくて、ただのintの配列に置き換えたかったので
もしこれでaの受取側がただの配列と同じように中身を見れるのであれば、
vector< vector<int> > a;
a[set][data] を a[data][set] に置き換えて受取側がアクセスできるかを見た方がいいのではと思いました。
これを実行するアルゴリズムなどは用意されているのでしょうか?
すいませんアドバイスお願いします
vector<int> s(set); int* a = new (*s)[data]; すいませんこれコンパイルできてません。
>>895 > int* a = new int[1000*10]
> として、サイズだけは確保し、後からa[data][set]や、a[set][data]として自由に中身にアクセスできないんでしょうか?
自分で書けばできないことはないが、やる必要がないと思う。
a[data*1000+set]
これで十分。
898 :
897 :2009/01/02(金) 10:40:37
ごめん間違えた。 a[data*10+set]
ありがとうございます。書けました! vector< vector<int> > vec; data = new int[data*set]; for(int k=0; k< set; k++){ for(int i=0; i< data; i++){ data[k+(i*set)] = vec[k][i]; } }
>>896 vector<vector<int> > (set, vector<int>(data)); じゃねーの?
配列でやるなら、 int (*a)[10] = new int[20][10]; でできるよ。
vector< vector<int> > v; v.resize(5); の場合、v[n] または v.at(n) で各要素にアクセス出来ますよね これ list の場合どうすればいいでしょうか? list< list<int> > lst; lst.resize(5); at() も operator[] も使えなくて詰まっています
std::advance(i, n)はイテレーターiを距離n分移動します なので *std::advance(list.begin(), 5); という式は概ねlist[5]のような意味を持ちます
list はそもそもそういう使い方はあまりしないものだが、 どうしてもしたいという場合は list< list<int> >::iterator it = lst.begin(); std::advance(it, 5); で *it を使おう。
>>902 listっていうのはそういうもの。
[]とかatを使いたいなら、listを選んだこと自体が間違い
>>902 なんでlistにしたのか知らんが、listを選んだ理由よりも、
vectorを選ばなかった理由を考えると、そういう間違いや迷いは起きない
vector, list, deque, set, map という色々な選択肢を とりあえず検討してみれ。
advanceの戻り値はvoidでしたねすんません
boost::nextなら戻り値が使えるな
911 :
902 :2009/01/04(日) 00:45:40
>>903-910 遅くなりましたがありがとうございました。
やっぱり設計ミスですね
vector に変更するようにしてみます。
コンテナにlistを好んで使う人たちを スキリスト教徒と言うらしいね
list厨はいっぱいいるけど deque厨ってあんまりいないよね
list便利だからな。検索は遅いけどヒットした結果はイテレータでキャッシュできるし。
dequeって性能が中途半端なんだよね
だが、それがいい。
俺はアロケート間隔を指定できる自作のdequeを作った。 もちろんランダムアクセスイテレータ対応のちゃんとしたSTLコンテナ。そんなに長くはない。500行しかない。
そういやstackのデフォルトがdequeなのってなんで?vectorの方が向いてそうなんだが
>>918 たまに追加時間がやたらかかる stack とか、ちょっと怖い。
もしかしてdequeってサイズが小さくなったときに解放するのか? vectorだと確保したままだからなぁ
そこあたりは流石に実装次第。
>>918 サイズが不定の場合はvectorは性能が悪い。
連続性が必要なければ、ほとんどの場面でdequeの方がいい。
deque舐めんな
0xでarrayが入ったらvectorの存在意義はどうなるのかなぁ
arrayは固定長だべ。 連続性と可変長が必要な用途には依然vectorが便利。
でもその両方が必要な場合ってそんなに多くないよな ないとは言わんが
arrayってスタックから取るんだよな? 大き目のバッファとか、ヒープから取りたい場合はvectorかな。 それともscoped_arrayみたいなのは入るんだっけ?
dequeといえばdequeからファイルに出力する場合って、 中身を一要素ずつ書き込むしかないのかな?
boost::serializeとか
dequeのためだけにserializeのコンパイルっすかw それはいいとしても、serializeの中でやっぱり一要素ずつ書いてたら 導入する意味は薄い気が。
ostream_iteratorか何かとcopyで
連続性保証されてないなら、一要素ずつ書き込むしかないと思うが。
dequeの実装に立ち入れば、チャンク毎に書き出すことも可能かもしれない。 駄菓子菓子、そもそもバッファリングされるから纏めて書いてもメリットは余り大きくはない。
たとえばdeque<char>をンMBも書く場合なら、 関数コールのオーバーヘッドもバカにできない木が。
インライン展開されるんじゃねーの?
ディスク入出力のオーバーヘッドに比べれば…
そもそもバイナリで書き出す必要があること自体、そんなに多くないだろ。
連続性は保証されてなくても実際はある程度連続してるんだから、 その連続具合を得る方法とかあるのかなと思ったんだが、無いのか。
試しにdeque<char>とvector<char>を5MBほど書き込んでみたら、 dequeがvectorの500倍ほどかかってワロタ VCのdequeの実装をみたら中身リングバッファで連続してない場合でも 2分割でしかないのに、これはダメだろ。
手元では全く同じだったぞ(STLport)
deque をリングバッファで実装って、できるのか? 要素数がいっぱいになったときにどうすんの?
リングバッファは間違いか
>dequeをリングバッファ バッファのリンクを順にたどっていくと一周するようにリンクしてあるってことだろうか。 それならリングバッファと言っていいと思う。 push_back()とpop_front()を対で繰り返すような処理の場合に バッファを再確保しなくていいから、ありなんじゃないかな。 #固定長のリングバッファ上を使用領域がぐるぐる回る バッファを追加するときの処理が面倒そうだけど。
それって単に空になったチャンクを取っといて使いまわすだけじゃ…
それって双方リストっていうんでないの?
deque舐めんな
char で試すとか馬鹿だろ。 しかもどうせ Debug モードなんじゃね? コピーコンストラクタのあるクラスで試せ。
vectorでもdequeでもコピーコンストラクタが走るのを避けるためにポインタ入れるほうが多くね?
そうでもない。
挿入/削除ぐらいじゃね?コピーコンストラクタのコストが気になるのって。 そんなに頻繁にするならlistでいいじゃん vectorの再配置がいやならdequeでいいし
vector は ・ 連続性が必要な場合 ・ サイズの変更をあまり行わない場合 に使う。 deque は ・ 連続性は必要ない場合 ・ 末端への要素の追加をよく行う場合 に使う。
連続性が必要かつ、サイズの変更が頻繁に行われる場合は?
本当にそんなことが必要かどうか 要件と設計を見直す
>>952 そんな都合のいいもん・・・
迷ったらvector使え
>>952 性能をあきらめる。
これがもっとも普通だろ。
>>954 エディタは普通listだろ
EmEditorがstd::listを使っているのは有名な話
STLには無いけどギャップバッファとかお勧め。 とはいえ、小さいファイルしか扱わんなら listとかvectorで十分と思うけどなー
dequeでよくない?
一方ロシアでは(ry
Data Structures for Text Sequences ってドキュメントがネットで読めるよ。 そこで一番推奨されていたのがPiece Tableって奴だったな。 が、linked listやgap bufferより複雑だ。 linked listは十分実用的で、出来合いのコンテナを利用できるのがいいな。
unordered_map<size_t(行番号), string> とか まぁ行単位のぶつ切りなので範囲コピーとかの速度はリストと変わらんが。
>>952 STL限定で連続性を求めたらその時点でvectorしかないんじゃ
値をガシガシ変更する時には list を使って、 データを作成し終えたら vector に変換する手もある。
>>964 STLじゃないけどbasic_stringは…?
C++0xならvectorよりarrayだわ
| C++0x C++0x C++0x | |
もう2009年何だからC++09と書けよ。それが嫌ならC++1xとでも書け。
>>968 arrayってvectorと違ってヒープにメモリ取ろうとしたらまた別にメモリ管理が必要にならない?
scoped_arrayがc++0xに入るか知らないが、そっちだろ。
vector<T>とvector<T*>でポリモーフィズムを実現してるんだけど、要素を追加するたびにポインタを更新しなきゃいけないから面倒 dequeなら連続性が保証されないから、要素追加でアドレスも変更されないんだよね?
14882:2003 23.1.2 Associative containers / 8 >The insert members shall not affect the validity of iterators and >references to the container, and the erase members shall invalidate >only iterators and references to the erased elements. Associative containers ってのは set とか map の総称な。
おー、ありがとう。
>>973 マジで?簡単なサンプルコードでは大丈夫だったのに
大きめにresizeするかlist使うしかないってこと?
>>974 のリンクにも、 vector や deque とは異なり、と書いてあるよ。
仕様をコードで試す習慣は止めろ。
糞仕様を元に実装することを長年強いられると そういう癖が付いちゃうんだよね仕方ないね
982 :
978 :2009/01/10(土) 17:34:55
>>979-980 仰るとおりです。
ランダムアクセスが欲しいんだけど、mapを使うかな。
他の人もありがとう。
仕様書読むだけでわかるってすごいな
985 :
デフォルトの名無しさん :2009/01/10(土) 20:20:54
>>985 おまえは小学校から日本語を勉強し直せ。
>>985 As associative containers, they are especially designed to be efficient accessing its elements by their key.なんでしょ?
Keyにintを使って代用しようかと
思ってたんだけど、
>>972 の使い方だとlist<T>とdeque<T*>の組み合わせなら再割り当ての問題は生じないね
自分の設計がアフォでした
988 :
987 :2009/01/10(土) 21:01:05
あ、でもlistじゃなくてmapなら要素の削除も簡単なのか スレ汚し失礼、もう一度じっくり考えてみます
>>988 「簡単」とか言うの禁止。
ビッグOとかで語れ。
アークション!
ランダウのO
993 :
デフォルトの名無しさん :2009/01/11(日) 00:16:02
うめ
997 :
デフォルトの名無しさん :2009/01/11(日) 09:31:27
998 :
デフォルトの名無しさん :2009/01/11(日) 09:32:49
>>982 「カレーが食いたいんだけど、ラーメンにしとくかな」
>>985 「ラーメンはカレーじゃないだろ」
1000 :
985 :2009/01/11(日) 09:37:26
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。