【C++】STL(Standard Template Library)相談室 11
1 :
デフォルトの名無しさん :
2009/01/11(日) 11:13:44
2 :
デフォルトの名無しさん :2009/01/11(日) 11:15:02
3 :
デフォルトの名無しさん :2009/01/11(日) 11:16:43
4 :
デフォルトの名無しさん :2009/01/11(日) 11:17:18
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
早速質問です。 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 と言われる。 これは何が間違ってる?
>>7 set< set<int> >の要素はset<int>だぞ? intじゃないぞ?
>>7 ↓こういうことしようとしてるのと同じ。結果がどうなってほしいのかわからん。
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
set<int>::iterator i(s.begin());
*i = 4;
10 :
デフォルトの名無しさん :2009/01/11(日) 18:05:33
>>7 std::set<int> v;
std::set< std::set<int> > s;
v.insert(10);
s.insert(v);
それ以前に空のコンテナからイテレータ作るのってまずくね?
別にまずくはないだろ begin()が有効とは限らないというだけで
空のコンテナってbegin()==end()になるんじゃないの?無効なの?
>>14 それであってる。イテレータ自体は有効だけど、デリファレンス(要素にアクセス)はできない。
どうしてもイテレータの良さが分からない vectorとかdequeとかならat()でfor文回せばいいじゃん 一個変数増えるし、洗練された手法には見えない だれか、熱く語ってくれないか
・全てのコンテナにat()が実装されているとは限らない。 ・全てのコンテナにoperator []()が実装されているとは限らない。 ・全てのコンテナにイテレータが実装されている。 ・全てのコンテナに対応したアルゴリズムを組む時に使える。 ・別に使いたくなければ使わなくても良いけど。
どっかのAPIからデータの集まりを「TheContainer」なるクラスで貰ってきたとしよう 君はそれを調べ上げて、めでたくその実体がvectorに過ぎないことを突き止め 中からatを引っ張り出してforループを書き各データに望みの処理を施した ここまでは万々歳だ ところがそのAPIのバージョンが上がって、TheContainerの実体はfantasticsetという ベンダがオリジナルで作り上げた超高性能で複雑怪奇なコンテナに変わった 君は互換性を保つために、fantasticsetの構造を調べ上げて、 各データに順次アクセスするためのカオスな繰り返し文を書いて、 それが正しく全データを重複なく渡っているかどうかのテストもしなければならなくなった 最初からTheContainer::iteratorを使ってループしてれば、こんな苦労をせずに済んだんだ どうだ素晴らしいだろう
>>21 俺も気になっている。
atや[]でもiが要るから互角だと思う。
連結リストはランダムアクセス時に後方要素を検索するのに時間がかかるけど、 内部にさらにリストを使ったりして10000個とかジャンプさせればかなり安定すると 思うけどな。 ちょっと自分で作って比較検証してみるか……
追加削除どうなるんだよという気がするけど
end のこと言ってるんだろうが 配列でもサイズが必要になるな。
>>23 それはスキップリストっていうデータ構造
結構古典的なデータ構造だから検証しなくても大体O(log N)になるよ
27 :
17 :2009/01/15(木) 20:34:43
>>18-22 抽象性が高い、と。速いとか、即役に立つというものでもないのね。
ちなみに、カウンタは変数に入りません、というイメージだった。
イテレータも宣言しだいでカウンタと同じように扱えるね。ちょっとforが長くなるけど。
なんとなく使ってみる気になった。
>抽象性が高い、と。速いとか、即役に立つというものでもないのね。 ……釣りだよね?
抽象度が高い事が即役に立つ事もある。
配列こそもはや使う気にならない。 イテレータがなくてもvectorやlistを使う。
固定長で大量に使う場合はまだ配列を使うなぁ それ以外はほとんどvectorだけど
boost::beginとendがあれば、もう配列も恐くない。 これでBoost/TR1のarrayももう役目を終えた。
vector は早く data() を実装してくれ。
初歩的な質問で恐縮ですが関数テンプレートにてコンテナの第3要素を返す場合、 どのように記述したらよろしいでしょうか? template <typename T> T get3rd(const T& container){ if( container.size > 3 ) return container.end(); typename T::iterator it = container.begin(); std::advance(it,2); return it; } std::vector<int> ivec(10,255); std::vector<int>::iterator it = get3rd(ivec); こうすると 'std::vector<_Ty>' から 'std::_Vector_iterator<_Ty,_Alloc>' に変換できません とエラーになってしまいます
戻り値型Tがコンテナ型なのにイテレータに入れようとしてる
ヒャッハーーーーッ!!!!! 戻り値を typename T::const_iterator にして iterator 部分を const_iterator にしたら解決しました。 関数の引数にconst T& としたので、普通のiterator は使えないのも見落としてました。 ありがとうございました。
こんなやり方もある template< template<typename, typename = std::allocator> class T, class V, class A> typename T<V,A>::const_iterator Get3rdValue(const T<V,A>& cont) { typename T<V,A>::const_iterator it = cont.begin(); std::advance(it, 2); return it; } 使い方 Get3rdValue<std::vector>(vi);
vectorやdequeで v.insert(v.end()+n,x); (n>0) とv.end() を 越えた位置を指定して挿入した場合の動作は、未定義でしょうか? 解説サイトを数件見ているのですが、記述が見つからないものでして。
39 :
デフォルトの名無しさん :2009/01/23(金) 08:32:12
>>38 23.2.4.3
Notes: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all
the iterators and references before the insertion point remain valid. If an exception is thrown other than
by the copy constructor or assignment operator of T there are no effects.
2 Complexity: If first and last are forward iterators, bidirectional iterators, or random access iterators,
the complexity is linear in the number of elements in the range [first, last) plus the distance to
the end of the vector. If they are input iterators, the complexity is proportional to the number of elements
in the range [first, last) times the distance to the end of the vector.
?
41 :
デフォルトの名無しさん :2009/01/23(金) 09:03:13
>>38 >>40 範囲外の反復子に対しての参照外しができないから、何が起こっても文句は言えん
>>41 なるほど要素を指してない無効な反復子を渡すのは、当然駄目ということですね。
ありがとうございます!
>>42 insert() 以前に、デリファレンスできないイテレータを前に進めた時点で未定義だよ。
insert(end,x) も未定義なの?
>>44 end() より先に進めてなければ最後に追加されるだけ。
>>41-42 読んでend()はデリファレンスできないから
許されていないのかと思った
47 :
デフォルトの名無しさん :2009/01/23(金) 12:06:21
48 :
デフォルトの名無しさん :2009/01/23(金) 12:12:42
>>45 gcc-4.3.2(mingw)
追加されないですよ。
std::vector<int> v;
std::vector<int>::iterator s;
std::vector<int>::iterator e;
v.push_back(0);
s = v.begin();
e = v.end();
std::cout << "before :";
while(s != e)
{
std::cout << *s << "\n";
s++;
}
v.insert(v.end() + 1, 10);
s = v.begin();
e = v.end();
std::cout << "after :";
while(s != e)
{
std::cout << *s << "\n";
s++;
}
>>45 endはsize() < max_size()内の有効な反復子でなければならない
>>46-49 「end() より先に進めてなければ」と書いといたのに。
> v.insert(v.end() + 1, 10);
51 :
デフォルトの名無しさん :2009/01/23(金) 12:21:38
流れ的に不安だから、念のためまとめとこう。 v.insert(v.end(), 10); // v の末尾に 10 を追加 v.insert(v.end() + 1, 10); // 未定義動作 v.end() + 1; // insert() 無しでこれだけでも未定義動作に突入
乙 end()まではOKなのか
データをファイルに保存してその内容を読み込んでlistに入れてます 単純なintとかなら出来るのですが、クラスなどになった場合、どのようにデータを取得すればよいでしょうか? // int の場合はこのようにしてデータを取得しています using namespace std; ifstream dataFile("test.dat"); if( !dataFile ) return -1; istream_iterator iterBegin(dataFile); istream_iterator iterEnd; list<int> lstData(iterBegin,iterEnd); dataFile.close();
シリアライズでぐぐれ
アリガトゴザイマース Boostがすごすぎる
endまで有効でend+1が無効なのは、配列変数へのポインタと一緒 char a[10]; char *p1=a+10; // OK char *p2=a+11; // NG char *p3=(a+11)-1; // NG (p1==p3は保証されない)
このうそつきめ!
p1 もデリファレンスした瞬間アウツなんだよな。
ポインタの加算演算って型の大きさに合わせて保存してるアドレスの値増減するだけじゃないの? デリファレンスしてなくてもだめなことあるの?
>>57 p1==p3が保証されないのってマジ?
もしそうならポインタ演算とか怖くて出来なくなるな
>>60 配列(非配列は要素数1の配列とみなして)の要素か終端までを指すように演算することは
できるけど、その範囲外を指すようにした場合は未定義動作になる。
char a[10];
a - 1; // 未定義動作
a + 10; // 終端なのでまだ大丈夫
a + 11; // 未定義動作
v.erase( v.end() ); v.erase( v.end(), v.end() ); 同じようで違うとゆー
>>63 ほんとだ。
5.7 Additive operators p5 より
> When an expression that has integral type is added to or subtracted from a pointer,
> the result has the type of the pointer operand. ...
> ... If both the pointer operand and the result point to elements of the same array object, or
> one past the last element of the array object, the evaluation shall not produce an overflow;
> otherwise, the behavior is undefined.
>>57-
>>68 この中にウソを言っているものがいる。
このうそつきめ!
67 :
67 :2009/01/24(土) 10:37:11
* * * + うそです n ∧_∧ n + (ヨ(* ´∀`)E) Y Y *
なんで皆騙されてんだよw (a+11)-1 != a+10 が成立する訳ないだろ、そんなんじゃとてもコンパイラ作れねーよ。 もちろん *(a+10)とか*(a-1)とかを使ったら無効なアドレスの参照だから何が起こるかわかんないけど、 ポインタ演算の時点では問題ないっての。
a+11がオーバーフロー起こす可能性があって、
その場合-1しても戻るとは限らないってことだろ
>>65 によると
ちょっと込み入った算式に入れてたりしたら、マズイ場合あるな。 もっとも、ポインタ値みたいなものへの計算値に基づいて 更に計算、みたいな恐いことはまずやらんけど。
>>68 実装依存なことと規格で保証されていることの区別のつかないバカ
実際の配置からすれば、ちょっと飛び出しても大丈夫ではあるよね
>>68 オーバーフロー時に例外が発生するCPUでは
(a+11) を実行した時点で例外が発生して比較自体が行われない可能性がある。
大人しくa+(11-1)しろってことだよ。
もちろん、自分がコンパイラを作るときは、 (a + 11) - 1をa + 10と同じ結果にしても構わないんだよ。
int *p=0; // nullpointrt; p+=1; assert(p!=0); ヌルポインタをインクリメントした結果が、非ヌルになることも保証されないんだよね やっぱり
オプション次第で変なアドレスを指す際にエラーとするコンパイラがあってもいいんじゃね。
その辺をどう扱ってもいいというのがすなわち未定義ということだ
文句があるならCの親のBCPLに言いな。
DSPなんかで、そういう問題が起こるケースがあったと思う int *getptr(int x) { static array[0x2000]; return array+(x*10); } offsetの計算を16ビットレジスタでやった方が高速化される環境だと 最適化によって x*10の結果の上位を捨てて下位16ビットしか使わないコードが生成されても文句が言えない
VS2005で動いている既存のプロジェクトにSTLport5.1.0を導入しようとしているのですが typeinfo.hのbad_castとbad_typeidがC2039・C2873エラーになります。 解決の方法がありましたら教えてください 個人の趣味で作ってるプログラムだし、例外捨ててコメントアウトかな…
84 :
82 :2009/01/29(木) 15:10:00
ありがとう、見てみました boost使ってないので少しわからないとこもありますが 5.0〜ならいける的な事が書いてあったりしますが、その後のバージョンなんですよね… 自分はtypeinfo.h内の::bad_cast記述部分二対して 存在しないのでエラーになっているのですが 上記ページだとtypeinfo.hをインクルードしているとかで混乱します
同じバージョンじゃないから確認とかしてないから話半分に IOSTREAM(S)をどっちで使うか設定するとこあるから それに似たbad_cast(exception)とかあるかも
86 :
デフォルトの名無しさん :2009/01/30(金) 20:36:39
ついったー(笑)でやれ
88 :
デフォルトの名無しさん :2009/02/01(日) 11:42:50
VC2005 Express Edition使っているんだけど streambuf_iteratorってどのヘッダインクルードすればいいの?
89 :
88 :2009/02/01(日) 12:09:33
ごめん istreambuf_iteratorにしてなかったから駄目だったんだ
90 :
デフォルトの名無しさん :2009/02/02(月) 14:05:11
VC9+MFCのアンマネージでmapは使えないのでしょうか? xtreeでアクセス違反が出るんですが・・・
>>91 それは何か使い方が間違っている。そしてそれは恐らくは、STLに直接関係ない。
93 :
デフォルトの名無しさん :2009/02/04(水) 18:31:55
すみません、vectorで質問なのですが //------------------------------------ #include <vector> using namespace std; int _tmain(int argc, char* argv[]) { vector<bool> bool_vect(10); bool& b = bool_vect[5]; vector<int> int_vect(10); int& i = int_vect[5]; return 0; } //------------------------------------- bool のほうで以下のコンパイルエラーが出てしまいます error C2440: '初期化中' : 'std::_Vb_reference<_MycontTy>' から 'bool &' に変換できません。 with [ _MycontTy=std::vector<bool,std::allocator<bool>> ] 回避する方法はないでしょうか?
何が目的で参照をとろうとするの?必要性が感じられないのだけど。
>>93 vector<bool>は使うなカス
詳しくはEffectiveSTL
なるほど、「std::vector<bool>はコンテナの要件を満たしていない。 」のですね。
ありがとうございます。
>>94 実際に必要性が出ているのは、もう少しややこしいコードで、
任意の型の参照を引数に取る関数に
その任意の型のvectorの要素をそのまま渡したかったのです。
とりあえずはboolだけ特殊化して回避することにします。
ただ、任意の型に対応するならvectorじゃなくて配列にした方がいいのかもしれないですね。
ともかくありがとうございました。
>>97 vector<T>::reference使えばいけるはず。
>>98 おぉ、STLっぽくなりました。
ありがとうございます。
bool なら deque 使うだろjk
deque<bool>とlist<bool>はコンテナだっけ
コンテナだよ
list<bool>・・・ 使い道が思いつかないな
つbitset
vector<int>のインスタンスがa,b,cとあって、aとbの要素をつなぎ合わせたcを作るにはどう書くのが一番シンプルですか? 例えばaに1,2,3が、bに4,5,6が入っている時、cを1,2,3,4,5,6にしたいです。
c=a; c.insert(c.end(),b.begin(),b.end());
intのvectorならこっちの方が速いし自然だよ
>>106 は中身がクラスの場合用
size_t a_n = a.size();
size_t b_n = b.size();
std::vector<int> c(a_n+b_n);
memcpy(c.begin(),a.begin(),a_n);
memcpy(c.begin()+a_n,b.begin(),b_n);
std::vector<int> v = (v1|pstade::oven::jointed(v2))|pstade::oven::copied;
>>111 vector と PODの組み合わせなんだから別にいいだろ
ovenは相変わらず反則だな
わざわざ型安全性を捨ててメモリ不正アクセスの危険を冒してまでmemcpyを使う必要はなかろう
コピーするにしても std::copy を使うべき
よっぽど速度が遅くて困らない限りは
>>106 で十分
>>108 さっそくバグってるなw
intが1byteの環境はあんまりないよね。
自分の場合こんな関数作ってユーティリティに突っ込んである template<typename T, typename Range> inline void range_extend(T &t, const Range &r) { t.insert(t.end(), boost::begin(r), boost::end(r)); } // c = a; range_extend(c, b);
>>108 vectorのイテレータがポインタではないライブラリではコンパイルエラーだぞ
c.begin() は &c[0] に置き換えないとダメ
というか
>>108 は memcpy にイテレータを直接渡してるじゃねーか
こんなん論外だ
!#include <iostream> #include <vector> #include <pstade/oven/jointed.hpp> #include <pstade/oven/sugar.hpp> #include <pstade/oven/copied.hpp> #include <pstade/oven/io.hpp> #include <pstade/oven/identities.hpp> #include <pstade/oven/initial_values.hpp> int main(int, char *[]) { namespace ov = pstade::oven; using namespace pstade::oven::sugar; std::vector<int> a = ov::initial_values(1, 2, 3), b = ov::initial_values(4, 5, 6); std::vector<int> v = (a >> b)|ov::copied; std::cout << (v|ov::identities); } sugarで(問題部分だけは)さらに短くかけるらしいです
>よからぬ場所に出入りしていると、当てにならない人物に出くわし、 &v[ 0 ] の代わりに >v.begin() を使うことができると言われるかもしれない。 (中略) >率直に言えば、 &v[ 0 ] の代わりに v.begin() を使うよう勧めるような人たちと付き合っているなら、 >交友関係を考え直す必要がある。 スコット・メイヤーズ著 ピアソンエデュケーション刊 Effective STL〜STLを効果的に使いこなす50の鉄則 p.73
そもそも >105 の質問は「一番シンプル」な方法を求めているんだから >106 が正解。 再確保によるロスを防ぎたかったら c.reserve(a.size() + b.size()) で準備してから 実行すればいい。 >108 の resize() では無駄な初期化( int の場合は 0 フィル)が入る。 要素型に依存する必要はまったく無い。
int の場合に memcpy() に最適化するというのも、ライブラリの実装やコンパイラが判別できる 範囲の話。
質問です。 STLはヘッダにその実装が書いてあるわけですが、 ということは「翻訳単位毎にコードが生成される」のでしょうか? a,cpp b.cpp 両方<vector>をincludeし、両方で vector<int> が使われていた場合、vector<int>のコードは2つ作られてしまうのでしょうか? EXEファイルの容量がガンガン増えるような気がするのですが・・・
>125 実装によるが、最終コードでは一つになっているのが普通。 C++ Templates The Complete Guide には 3 つのモデルが載ってる。概要は以下の通り。 1. Greedy Instantiation 翻訳単位ごとにインスタンス化するが、リンカで一つだけ残す。 2. Queried Instantiation 共有のデータベースを持ってそこに登録する。 3. Iterated Instantiation リンク時に足りないものを検出してインスタンス化。
真・スレッドリスターター。。。( ̄ー ̄)ニヤリッ
アヌスストッパーじゃないのか。
130 :
デフォルトの名無しさん :2009/02/23(月) 18:07:27
関数オブジェクトの使い方として、以下のような記述は許されますか? // generate アルゴリズムを使ってコンテナに公差1の等差数列を代入する template < class T > class Gens { public: Gens() : s_( 0 ) {} Gens( T i ) : s_( i ) {} T operator () (){ return s_++; } private: T s_; }; int main() { vector< int > vector1( 20 ); Gens< int > gens( 10 ); // 問題はココと generate( vector1.begin(), vector1.end(), gens ); // ココ } 普通は generate( vector1.begin(), vector1.end(), Gens< int >() ); のように書きますが、 あらかじめオブジェクトを構築しておいて、 そのオブジェクトを引数として渡すというものです。 上記の例ではあらかじめオブジェクトを構築することで ジェネレータが作り出す数列の初項を10に設定しています。
>>130 >上記の例ではあらかじめオブジェクトを構築することで
>ジェネレータが作り出す数列の初項を10に設定しています。
なら
generate( vector1.begin(), vector1.end(), Gens< int >( 10 ) );
でもインジャネーノ?
コピー禁止すりゃいいんじゃね?
誰にも突っ込んでもらえなかったけど、コピー禁止してどうやって渡すんだ orz
>>133 たしかに規格上は保証がないかもしれないが、なんだか屁理屈に聞こえる。
>>136 同感だな
内部状態を持つ関数オブジェクトって普通にありえるからな
なんか現実を無視して重箱のすみを突いているって感じだな
いや、これははまるぞ 移植してバグったとき、大変そうだ
139 :
デフォルトの名無しさん :2009/02/24(火) 00:01:50
ん? マッサーの STL 本では generate のサンプルで内部状態を保持しているし メイヤーズの Effective STL でも、関数オブジェクトの利点は 「必要に応じていくつでも状態を格納できること」と書いてるぞ?(たとえば p.161 ) 述語は純粋関数でないとだめだけど。 サッターの C++ Coding Standardsでは 「述語は関数オブジェクトの部分集合である」( p.172 )としていて すなわち述語でない関数オブジェクトは純粋関数でなくても良いということになってるぞ? どっちなんだ。
140 :
デフォルトの名無しさん :2009/02/24(火) 00:05:52
ちなみに、generate の第三パラメータは述語ではないので、 (マッサー、メイヤーズ、サッターの本にあるとおり) 純粋関数でなくても良いということになる。
141 :
デフォルトの名無しさん :2009/02/24(火) 00:12:15
今、シルトの本も調べてみたが、やっぱり関数オブジェクトの利点として 「値を格納したり、追加機能を実装できる」( p.230 )と書いてるな。
すまん、全部 age ちまった・・・ orz
vectorの連続性と一緒だな 普通はコピーなんてしないし、規格作った方もそんなつもりじゃなかったけど ちゃんと書いてないせいで信用できないし、コピーしちゃう実装を誰かが作っても責められない そんな誰も得しない状態 0xで直るんかね
vectorの格納領域は「必ず」連続するようになったのは1998年以降だから まぁ、いまどきのコンパイラならもう必ず連続すると考えていいんじゃないの。
std::vector<int> v; v.reserve(10); ... // v に値を格納 std::copy(v.begin(),v.end(),std::ostream_itreator<int>(std::cout,",")); このコードの copy 内の ostream_iterator... の部分て何を行っているのですか? コンテナの要素をループで書き出してるのは分かるのですが、内部でどのような処理をしているのでしょう?
>>138 俺もはまった
boost::refして誤魔化した
ええ、どこのベンダだよ
vectorの格納領域と同じで、標準化委員会がどっかで修正コメントだしてないのかな?
>>130 俺なら output_iterator を受け取る関数を作って back_inserter を渡す。
std::vector なら reserve してからね。
>>133 良くないのはそうだけど、総和とかには使うし、命名とかコーディングスタイルの話になるんじゃないか?
>>146 それどこのSTLライブラリ?
で、どんなコードではまった?
>>149 ライブラリの内部実装の話を命名やコーディングスタイルでどうするの?
>149 総和系なら accumulate があるべ。
状態を持つと並行処理できないじゃないか。 なーんてね
>>151 内部状態を持つ関数オブジェクトを使う話で、内部実装の話はしてないよ。
使わないほうがいいけど、使うなら注意を喚起するとか、専用の関数を作って封じ込めるとか、という話。
>>153 全くその通りでした。
mapは構造体をキーに持つことができないのでしょうか? 具体的には、mapを使って2枚の画像の対応点を記録しようとしています。 typedef struct point { int x; int y; }point; map<point, point> correspond; point p1, p2; /*p1とp2の座標を入力*/ correspond.insert( pair<point, point>(p1, p2) ); としてコンパイルするとerror C2784が出ます。 環境はVS2008、XP SP3を使っています。 どうしたら解決できるでしょうか?
エラーの内容から二つのpointを比較できないコードであるということがわかるので、mapの為に比較関数を用意する。 方針としては、グローバルにpointの大小を判別するbool operator<(const point&, const point&)を定義するか、 correspondの宣言の歳にmap<point, point, compare_t> correspond(compare);とする (ただしcompare_tは戻り値boolで引数に(const point&, const point&)を取ることができる関数オブジェクトまたは関数の型で compareはそのインスタンス)
>>157 素早い回答ありがとうございます。
pointのxとyどちらでソートすべきか比較関数を用意してやればよいということでしょうか?
うん、例としては bool f(const point& lhs, const point& rhs){ return lhs.x < rhs.x && lhs.y < rhs.y; } のようなものを定義して map<point, point, bool(*)(const point&, const point&)> correspond(f); かな? operator<を使う方法についてはeffective C++とか参考にすれば、 綺麗に実装する方法が載ってると思う
>>159 具体例までありがとうございます。
map 比較関数 でググったらいくつか例も出てきたので出来そうです。
よく考えるとmapは2分木を利用してるんだから自前の比較関数を用意してやる必要があるのは当たり前ですね。
勉強になりました。
std::list<T>をTにすればコンテナ全種に使えるようになるはず。
よくわからないけどこういうこと? template<typename T> std::ostream &print(std::ostream &ost, const T &cont) { ost << "["; std::copy(cont.begin(), cont.end(), std::ostreambuf_iterator<T::value_type>(ost, ",")); ost << "]"; return ost; }
コンテナを取るんじゃなくて、algorithmみたいに範囲を取るようにすれ。 template<typename Iterator> std::string to_str2(Iterator first, Iterator last) { std::ostringstream oss; Iterator it = first; oss << "["; if (it != last) { while (true) { oss << (*it); ++it; if (it == last) break; oss << ", "; } } oss << "]"; return oss.str(); }
まぁそれだけだとlist<list<...>>みたいなのに適応できないけどな
166 :
161 :2009/02/27(金) 23:02:22
>>162 ほんとですね、全部なおしました
std::ostream& operator<<(std::ostream & rhs, const <T>& lhs)はダメなんですね
当たり前なんでしょうけど
>>163 こういう書き方もできるのですね、、、
p to_str(dlist)かp 'to_str(std::list<Data, std::allocator<Data> > const&)' (dlist)でgdbから呼べるのですが、
ostreamかtemplate使うと消える?みたいなのでObject.to_string()とテンプレートではないto_str(x)は用意するので
ostreamやostringstreamを極力使わずにできればなと
>>164 ,165
Iteratorの中身がコンテナじゃなさそうな場所に使ってみます
とりあえず、rhsは right hand side(右側)の略なんだから lhs << rhs って形にしようぜw
関数オブジェクトにしといてfor_each()じゃだめなのか
こんな感じ? template <class T> struct Out { void operator()(T& i) const { std::cout << i << ' '; } }; int main() { int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::list<int> aa(a, a + sizeof(a) / sizeof(a[0])); std::for_each(aa.begin(), aa.end(), Out<int>()); }
ostream_iteratorにassignという手も
例としてよく引き合いに出されるのは ostream_iterator に copy だと思うが・・・
for_eachを使うと copy よりも凝った出力形式を作れるってくらいかな
#include <pstade/oven/io.hpp> #include <pstade/oven/make_range.hpp> int main() { namespace oven = pstade::oven; std::list<int> l = a|oven::copied; std::cout << (oven::make_range(l)) << "\n"; }
>>175 for_eachの戻りはコピーされた関数オブジェクトに内部状態が反映されてるんじゃなかった?
>176 関数オブジェクトに全要素を通して処理した結果の状態が保持されていることを期待するだろうが、 極端に言えば各要素の呼び出し毎に新しくコピーした関数オブジェクトを渡されたりすると、期待する 結果と異なる。 参照使うなりコピーされても大丈夫なようにはできるからまったく使えないは言い過ぎ。 とはいえ、そういう用途なら accumulate 使えばいいじゃん、とは思う。
boost::ref使って渡せばいいんじゃないか。boost::mpl::for_eachではうまくいった
char *buf = new char[n]; //(snip) std::istream is(pointer_streambuf(buf, buf_size)); みたいな感じで、ポインタをバインドできるstreambufってある? ないならつくるんだけど。
181 :
180 :2009/03/28(土) 19:11:47
っていうか勢いあまって作ってしまったんだけど、標準かboostにあるならそっち使う。
あと、
>>180 の訂正:
x char *buf = new char[n];
o char *buf = new char[buf_size];
istrstreamか? 廃止予定だけどw
>>182 おk。でも廃止か。
strstreambufも廃止なんかな。
先にstringstream使ってて、basic_stringにしか対応してないから、
strstreamは無視してたわ。
vectorについて、ある時点でのvectorの中身を参照するような配列のポインタ、 ちょうどstringのc_strのようなものはありますでしょうか。 allocatorのpointerやaddressがそうなのかと思ったのですが、 vector<int> v; v.push_back(1); v.push_back(2); const int* p = v.get_allocator().const_pointer(); for(int i=0; i<v.size(); i++) cout << p[i]; のように書いても大丈夫でしょうか。
いやいや、むしろ&v[0]とか&v.front()でいける。 アロケータのconst_pointerはT const*のtypedefだし、addressは&演算子と同じこと。 事実上、死に設定。
どうしてイテレータじゃだめなのかすら?
v.at(i)でええやん
やりたかった例としてはこっちの方が良かったかもしれません。 int buf[256]; if(v.size()<256) memcpy(buf, &v[0], v.size());
C++0xならv.data()が使えるんだけどな
SGIがなんかあれなんですよね
2度目のchap11
193 :
インドリ :2009/04/09(木) 10:03:38
淫鳥
久しぶりにSTLPort使おう思ったら、ビルドまでずいぶん便利になってるのな……
STLport 5.2.1とboost 1.38.0を一緒に使おうと思ったらビルドエラーが出まくって無理だった
ちょw
198 :
デフォルトの名無しさん :2009/04/22(水) 21:47:20
自分で作ったクラスにイテレータを実装する方法がいまいちわかりません。 どこかにいい解説はないでしょうか? それとも皆 boost::iterator_facade を使ってるのかな?
>>198 boost::iterator_facade で何か不満でも?
boostはインストール禁止なんです…
なんでSTLport5.2.1をMinGWでビルドしようとすると "awk"が見つかりません のエラーが出るの? STLport5.1.5までは何の問題もなくビルド出来ていたんだが
>>200 じゃ、 boost::iterator_facade の実装を見るとか。
とりあえず作ってみたものと、その問題点をここで晒してみるといいかもしれない。
>>198 std::iteratorのマニュアルを読んで、
std::istream_iteratorみたいな単純なやつを読む。
インストールというか置くだけで使えるよ! そういうことではないんだろうが
>>205 その前者は、
>ある値と一致する範囲の一番最初を返す
と書いてある見出しとも矛盾している。
後者が正しい。 もともと lower_bound と upper_bound は value を挿入可能な半開区間 [ lower_bound, upper_bound ) を探すためのアルゴリズムだから。 これは equaLrange の結果に等しい。 って、マッサー本に書いてあった。確か。
前者はlowerとupperの解説文章が逆ってことかな
>>206 本当ですね。
>>207 なるほど。
>>208 逆としてみても、「見つからない場合はlast。」というのはおかしいですね。
あと、引数や戻り値のイテレータがランダムアクセスイテレータなのが気になります。
どうもありがとうございました。
class A { private: int m_nTime; public: A( int nTime ) : m_nTime( nTime ) {} int GetTime() { return m_nTime; } } typedef map< int, A * > AMap; typedef AMap::value_type AMapValue; typedef list< AMap * > AMapList; 例えば上記の様な定義をしていて、 メイン関数内で、AMapList内をイテレータを利用して、特定のAMapの「Key」部を検索し、 見つかったら、AMapの「Value」部を出力(クラスAのGetTime()を呼び出す)するような処理 をさせたいのですが、どうすれば実現できるでしょうか? また、listコンテナの中にmapコンテナを突っ込むような利用は、一般的にあまりされないの でしょうか?
>>210 それ、mapじゃなくてpairじゃいかんの?
>>210 とりあえず自分で書いたやつを見せてみろよ。何がわからんのかわからん。
>>210 1. AMapListから特定のAMapのイテレータを取得する。これをiとする
2. (*i->find(キー))->GetTime()
mapをlistに入れた構造が必要な場合はmapをlistに入れるよ
…としか答えられないな
(*i)->find(キー)->second->GetTime();じゃね?
vectorの要素ってCopy ConstructiveとAssignable以外には必要ないはずだよな? VC9のSTLはDefault Constructiveを要求してきやがるんだが……。 #include <vector> class hoge { hoge(int) {} hoge(const hoge&) {} hoge& operator=(const hoge&) { return *this; } }; int main() { std::vector<hoge> vec; vec.resize(10); }
>>216 それ、 resize() のあとの要素が何で初期化されてることを期待してるの?
ああ、ごめん書き間違えた resizeの第二引数にhogeの適当なインスタンス渡してもだめなんだよ。
g++つかえば
>>216 bcc 6.1.0でも次のようなエラーが出るよ
エラー E2285 vector 608: 'hoge::hoge()' に一致するものが見つからない(関数 vector<hoge,allocator<hoge> >::resize(unsigned int) )
エラー E2247 vector 1179: 'hoge::hoge(const hoge &)' はアクセスできない(関数 vector<hoge,allocator<hoge> >::_Insert_n(_Vector_iterator<hoge,allocator<hoge> >,unsigned int,const hoge &) )
エラー E2247 vector 1203: 'hoge::hoge(const hoge &)' はアクセスできない(関数 vector<hoge,allocator<hoge> >::_Insert_n(_Vector_iterator<hoge,allocator<hoge> >,unsigned int,const hoge &) )
エラー E2247 xutility 1681: 'operator hoge::=(const hoge &)' はアクセスできない(関数 std::void fill<hoge *,hoge>(hoge *,hoge *,const hoge &) )
エラー E2247 xutility 1551: 'operator hoge::=(const hoge &)' はアクセスできない(関数 std::hoge * _Copy_backward_opt<hoge *,hoge *>(hoge *,hoge *,hoge *,_Nonscalar_ptr_iterator_tag) )
エラー E2247 xutility 1515: 'operator hoge::=(const hoge &)' はアクセスできない(関数 std::hoge * _Copy_opt<hoge *,hoge *>(hoge *,hoge *,hoge *,_Nonscalar_ptr_iterator_tag) )
エラー E2247 28: 'hoge::hoge(const hoge &)' はアクセスできない(関数 std::void _Construct<hoge,hoge>(hoge *,const hoge &) )
*** コンパイル中に 7 個のエラーが発生しました ***
あら間違えて書き込んでしまった ちなみにMinGW5.1.2(gcc3.4.5) + STLport5.1.7で同じソースをコンパイル すると vector1.cpp:11: error: no matching function for call to `hoge::hoge()' vector1.cpp:5: note: candidates are: hoge::hoge(const hoge&) vector1.cpp:4: note: hoge::hoge(int) _algobase.h: In function `_OutputIter stlp_priv::__copy(_RandomAccessIter, _RandomAccessIter, _OutputIter, const stlp_std::random_access_iterator_tag&, _Distance*) [with _RandomAccessIter = hoge*, _OutputIter = hoge*, _Distance = ptrdiff_t]': _algobase.h:250: instantiated from `_OutputIter stlp_priv::__copy_ptrs(_InputIter, _InputIter, _OutputIter, const stlp_std::__false_type&) [with _InputIter = hoge*, _OutputIter = hoge*]' (...以降あまりにエラーが多いので省略) で、やはりDefault Constructiveを要求してくるので、 Dinkumwareだけの問題ではない事がわかる。
ちなみに public: hoge() {} を入れると両者とも一発で通る。
resizeのプロトタイプは void resize(size_type sz, T c = T()); だからデフォルトコンストラクタがないと通らないこと自体は当然
ただ実装はSTLPortもDinkumwareも void resize(size_type, T) void resize(size_type) のように二つの関数に分けてるがな
#include <vector> struct hoge { hoge(int) {} hoge(const hoge&) {} hoge& operator=(const hoge&) { return *this; } }; int main() { std::vector<hoge> vec; vec.resize(10, hoge(5)); return 0; } これで gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) gcc version 4.3.2 20080827 (beta) 2 (GCC) ※ on cygwin VC7.1 cl (Version 13.10.6030 for 80x86) VC8 cl (Version 14.00.50727.762 for 80x86) VC9 cl (Version 15.00.21022.08 for 80x86) bcc 6.10 Comeau 4.3.9b + VC7.1 Comeau 4.3.9b + VC8 Comeau 4.3.9b + VC9 Comeau 4.3.9b + bcc 6.10 全部通るよ?
>>225 むしろそれだけの環境を使いこなすお前は何者
俺の場合、<memory>218行目の typename _Alloc::value_type _Val; でもろにDefault Constructor要求された。
こりゃひどい
ワラタ
ついでに言うとdefault constructibleだ。
いいもの見させてもらった 記念パピコ(゚∀゚)
あなたをprivateです。
わたしはあなたのpublic
ごめんなさい、ずっとfriendでお願いします
delegateな俺の心はこっぱみじん
NULLぽ
240 :
デフォルトの名無しさん :2009/05/04(月) 16:40:11
- -―- 、 /...::::::::::::::.. ヽ / ..:::::::::::::::::::/\ ヽ /..:::/::::/::::// ヽ l:. l. l:::::!::::/●) (●)|:: | . !:::l::::l/// ,, ///l:i:l いやぁぁぁん ヽ:i::!、 r ― ァ ノノ' ` l\`ー './ ノヽ \_フ.ヽ |_ 丶 ヽ . | |' 初心者)
241 :
デフォルトの名無しさん :2009/06/07(日) 14:44:09
>>241 なぜここに?
0xスレに貼るのならともかく。
ぶつぶつ会終わったよー
244 :
デフォルトの名無しさん :2009/06/18(木) 11:57:11
質問です vector<int> v; v.resize(100); とやった際に、確保されたv[0]〜v[99]は、0クリアされていることは保障されているのでしょうか? 自分で試しにやってみる限り0クリアされているのですが、なぜわざわざクリアされているのか疑問です。 (mallocとかで確保したメモリは、クリアされていないですよね。なのになぜvectorだとわざわざそんなことを?) 自分で試した環境は、VS2008C++Express です
>>244 新たに確保された要素はデフォルトコンストラクタで初期化される
void resize( size_type sz, T c = T() ); だから。 なんで値で埋めるのかは…仕様決めた人に聞いてくれ。 領域確保だけならreserveがあるし。
保障されてたんですね。 どうもありがとうございます
×保障 (ある事態への)備え。プログラム的にいうとtry〜catch ○保証 約束されていること。プログラム的にいうとassert()を抜けるのが間違いない状態
自作のクラスからヌルポの例外投げたいんだが std::exceptionに標準であったりしない? ヌルポ
>>249 標準にはない。どういう場面で投げたい?
場合によっては標準の例外の方が意味が明確になるかもしれない。
>>250 えっとね
データコンテナっぽいクラスを作ってて
->演算子とかで中のデータにアクセスさせてるんだけど
中のデータがnullの時は->演算子の処理中に例外で中断させたい
>>251 なるほど。標準にマッチするのはなさそうかな。
boostになら何かそんなのあったな
std::runtime_error でいいんじゃネ
256 :
デフォルトの名無しさん :2009/06/29(月) 22:31:41
vector で、バッファ拡張で要素をコピーするとき、メモリイメージをコピーではなく、 コピーコンストラクタでコピーして、コピー元は delete するのって何故だっけ?
俺のLv7のESPで読んだところ swap技法か例外安全について聞きたいらしい
なんかいろんな話がごっちゃになってるような気がする
>>256 メモリイメージをコピーで問題が発生しない保証は無いじゃないか
>>256 仮にオブジェクトが自分のアドレスを使って何かしてるとしたら
>>256 intなんかはメモリ領域のコピーでいいけど、
smart_ptrなどではオブジェクトのコピー処理を実行する必要があるから
262 :
261 :2009/06/30(火) 07:50:46
別にそうでもないか 忘れてくれ
時々でいいので
>>261 の事を思いだしてあげて下さい
>>262 >>256 smart_ptrはコピー時に参照回数を変更するひつようがあるんでメモリイメージコピーはできないからそうでもあるよ。
メモリ領域コピーして元領域のメモリをそのまま解放したらカウント維持で問題ないからそうでもない そういう問題ではない
ものすごく基本的な質問をさせてください。 std::vectorで100個(数は可変)のデータがあって これの最初20個ぐらい(数は可変)のデータを削除して 前に詰めたいのですが、どうすればいいのでしょうか? erase (remove( ではダメでした。
v.erase( v.begin(), v.begin() + 20 );
できました! ありがとうございました!
初めて出てきた要素に対してのみ動作するunique_transformを実装してるのですが unary_functionを継承した関数オブジェクトだけでなく 普通の関数も渡せるようにするにはどうすれば良いのでしょうか? template<class InputIterator, class OutputIterator, class UnaryFunction> InputIterator unique_transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction unary_func){ set<iterator_traits<InputIterator>::value_type> s; while(first!=last){ if(count(s.begin(),s.end(),*first)>=1){++first;} else{ s.insert(*first); *result=unary_func(*first); ++first;++result; } } return last; } struct i:public unary_function<int,int>{ int operator()(int a)const{return a;} }; //main側 string a="abcadbc"; string b; unique_transform(a.begin(),a.end(),back_inserter(b),i()); cout << b << endl; これを int id(int n){return n;}を定義して unique_transform(a.begin(),a.end(),back_inserter(b),id) などと出来るようにしたい 後、STL実装ってVisualStudioのどっかのフォルダに入ってるんですかね?
あ、特に修正しなくてもidも渡せるのか
>>269 は忘れてください
忘れました。^^
std::vector<Object*> objs; をソートしたいのですが、どうすればいいのでしょうか? Objectクラスにはbool operator< (const Object& lhs, const Object& rhs); が定義されています。 objs.sort (objs.begin(), objs.end()); とやると、上の<を使わずにポインターの値そのものを使ってソートしてくれやがります。
Object& じゃ型が違うんじゃ Object*& じゃないの
>>274 ポインタ型同士の比較は272が言っているとおりコンパイラが組込で持っているから、
そんなのは定義できない。
というわけで
>>273 。
> コンパイラが組込で持っている ああ、すっかり忘れてた
bool operator <(Object* o1, Object* o2); グローバル関数のオーバーロードで行けるかと思ったけど、 引数の片一方がクラスじゃねえぞ、とコンパイラにキレられた
ObjectPtrクラスを作って、Objectの&を上書きしてPtrクラスを返すようにすれば
279 :
272 :2009/07/29(水) 19:03:15
みなさん、ありがとうございます。 言っていることがさっぱりわからないので、勉強し直してきます。
うだうだ言っていないで、こう書けばいい。 #include <boost/lambda/lambda.hpp> using boost::lambda::_1; using boost::lambda::_2; std::sort(objs.begin(), objs.end(), *_1 < *_2);
lambda さんかっけーっす!
なるほど、覚えておこう std::sort(objs.begin(), objs.end(), *boost::lambda::_1 < *boost::lambda::_2);
日本横断 STL の旅 SL の見間違いだった
そういえばlsってよくslと打ち間違えて電車走るな 電車は飽きたので、slって打ったらSTLを宣伝するディストリを誰か作って
>>284 走っているのは蒸気機関車であって電車ではない罠。
つーか、適当なSTL紹介文書を垂れ流すスクリプトを作って問題のslよりも上流に置けばいいだけじゃん。
>>287 別に区別するともしないとも言ってないんでないの?
STLの中にはlistと別に_Treeクラスがある
listのノードは_Next, _Prevがあるだけだが
_Treeのノードは_Parent, _Left, _Rightがあるから
手が一本多い=構造に違いがある
っていうレスを求めてるのか?
>>287
標準で定められてるSTLコンテナはvector,deque,list,set,multiset,map,multimapだけ treeはないし、あったとすればそれはベンダの独自拡張だから何とも言えない
VCだと確かmapとsetの親がtreeだったな
今時二分木とかw ハッシュマップだろjk
おまえのハッシュはソート済みにしてくれんのか
おうよ、常にソート済みさ
鬼才あらわる
297 :
デフォルトの名無しさん :2009/08/21(金) 12:08:50
std::stringstreamは、ostringstreamとistringstreamの多重継承であると知った std::stringはstd::stringstreamと関係してる?別物?
>>297 嘘乙
stringstreamはiostreamを継承している
int a[10]; std::generate(a, a+10, rand); で乱数を入れられますが、rand()%100を入れたい場合、bindとか使ってどう書けばいいですか? lambdaならできそうな気はしますが。
>>300 generate(a, a+10, bind(modulus<int>(), bind(rand), 100));
TR1(bind)無しだと関数オブジェクト作らないと無理かな。
bindが使える環境ならTR1のrandomを使った方が良いような気がする。
302 :
300 :2009/08/26(水) 23:08:17
>>301 なるほど、bind(rand)ならば、評価のたびにrandが呼び出されるというわけですね。
この点がわかっていませんでした。
ありがとうございました。
突然すみません 文字列のソートができる、コンテナを教えてください。 と聞いたら、どんな順番に並びかえるんだと突っ込みを受けることは甘受します
STLはすばらしいのでソートはコンテナに依存しません
>>305 mapは常にkeyでソートされている。
>>303 Sequence コンテナである vector, deque, list, basic_string であればすべて可能。
配列だってソートできちゃう★ そして、マンバ関数でいいならリストでもソートできる。すごい。
マンバ関数? それどこの踊り?
ヤー坊 マン坊 天気予報
関数だってソートできちゃう★すごい。
逆だろ 危うくスルーするとこだったwww
313 :
デフォルトの名無しさん :2009/09/01(火) 05:31:26
fstreamで、タブ区切りのテキストデータを読み込んでいます。 途中にスペースを含むファイル名が出現すると、バラバラに読み込んでしまいます。 wsはタブと改行のみで、半角スペースは除外するような指定はできないのでしょうか?
デリミタの細かい指定をするときはboost使ってたけど.なんて奴だっけな
boost::tokenizer かな
spiritだろ
strtok
ああ boost::tokenizer だ
一方私はsscanf()で済ませた。
誰の勝利だ
すとろーすっぽすっぽ
イテレータというのは ポインタ演算にしか見えないんですが、何が良いんですか? 普通に書くよりイテレータに代入してから回す利点を教えてください
traits iteratorでぐぐれカス
>>322 もうちょっと抽象的なので、 vector のイテレータでも list のイテレータでも、
ある程度おなじように操作できる。
> ポインタ演算にしか見えない わざとそうなっている。 線形リストや2分木など、配列以外のデータ構造でも 配列と同じように要素を辿れるのがイテレータの存在意義。
イメージがつかめました。 ありがとうございます。
constのvalarrayのoperator[]って、何でconst T&ではなくTを返すんだろう? ↓みたいな関数も、aは意味的にはconstなのに、引数にconstをつけないか、中でconst外ししないと使えない。 void hoge(const std::valarray<double> &a) { memcpy(dest, &a[0], sizeof(double) * a.size()); }
数値計算とかしないならvectorでも使ってください。
valarrayてメモリ上連続性保証されてんの?
>327 > 14882:2003 26.3.2.3/4 > Likewise, the expression &a[i] != &b[j] evaluates as true for > any two non-constant arrays a and b and for any size_t i and > size_t j such that i is less than the length of a and j is less > than the length of b. This property indicates an absence of aliasing > and may be used to advantage by optimizing compilers. エイリアス(同じアドレスを持つオブジェクト)を排除することで、最適化に寄与する ことを意図しているから。つまり >328 >329 > 14882:2003 26.3.2.3/3 > The expression &a[i+j] == &a[i] + j evaluates as true for all > size_t i and size_t j such that i+j is less than the length of > the non-constant array a. だから連続性は保証されているはず。
>>328 いや、数値計算なんで。
>>330 thx.
vectorと比べてみたら、速度が変わったし、確かに最適化が効いてるみたい。
restrict導入しろよというお話しでした
C++にrestrictを導入するのはちょっと考えれば無理なのが分かるはずだが
>>334 知ったか乙
どこがどう無理なのか説明してみろよ
336 :
334 :2009/09/22(火) 21:14:02
嘘言ってごめんね
STLコンテナって、なんで最初から比較の時ポインタを実体参照する仕組み無いの? いちいちポインタ用のComparatorを自前で用意するのが面倒なんだけど。
>>338 どっちがお望みかわからないからだろ。jk
std::deref_less を用意してくれればよかっただけだろう。
341 :
338 :2009/09/30(水) 20:44:23
>>340 同意。てか0xにも盛り込まれてないのが不思議で仕方ない。
boostとかサードパーティのものでも使えってのかな。
面倒くせぇ #include <boost/type_traits/remove_pointer.hpp> template <typename T, template <typename Y> class Pred> struct deref : public Pred<typename boost::remove_pointer<T>::type> { bool operator()(const T& lhs, const T& rhs) const { return Pred<typename boost::remove_pointer<T>::type>::operator()(*lhs, *rhs); } }; //std::set<int*, deref<int*, std::less> > container;
std::set<int*, [](int* p, int* q){return *p < *q;}> container;
auto pcomp = [](int* p, int* q){ return *p < *q; } std::set<int*, decltype(pcomp)> container(pcomp);
独自のiteratorを作る場合、STLアルゴリズムに使えるようにするには 最低限どんな仕様が要求されるのかを知りたいんですが こういう仕様書のようなものはいったいどこで仕入れてるんでしょうか?
>>345 どこにあるんでしょうね
言語の仕様じゃなくてあくまでもライブラリ内のお約束
という説明にずっと出会わなかったせいでSTLの勉強は大変だった
>>345 コンテナを使っているうちに、いつのまにか
forward_iteratorとかreverse_iterator
とかに詳しくなっていくもんだろ。
ギリシャ語の名前の人(読めない)のサイトでイテレーターの作り方が載ってました
そのウソの説明を信じてSTLのiteratorの仕様が言語の仕様だという事を知らなかったのか そりゃ勉強も大変だっただろうな
5個くらい上だろう
昔はともかく、今はSTLもC++言語仕様の一部。 組み込み型とかと違って、コンパイラが直接サポートしてくれるわけじゃないので、 そういう意味では「お約束」なのも事実だけど。
コンテナ及び、配列の要素に下記の関数を適用し、結果を指定したコンテナに格納したいのですが 変数が3個あり(点数、平均点、標準偏差)どのアルゴリズムを使えばよいのか分かりません、 どうしたら幸せになれますか?それともアルゴリズムの適用はあきらめるべきでしょうか? 適用したい関数 偏差値 = (点数 - 平均点) × 10.0 ÷ 標準偏差 + 50
アルゴリズムの適用ってなんやねん
transform とか、for_each のことですが
それを諦めるってどういうことやねん
まず適当なアルゴリズムを使って平均点を求めろ。 次に適当なアルゴリズムを使って標準偏差をを求めろ。 最後に適当なアルゴリズムを使って偏差値を求めろ。
点数、平均点、標準偏差は既に適当なアルゴリズムで求まってます 問題は最後の偏差値を求めるのに、transform や、for_each が使えなくて 他に良い方法が無いかと思案してるところです要するに、下記のコードを、STL 風に書くにはどうしたらいいですか? // 偏差値 = (点数 - 平均点) × 10.0 ÷ 標準偏差 + 50 // DeviationValue(偏差値)、*iter(点数)、AVE(平均点) 、SD(標準偏差) vector<double>::iterator iter = rhs.begin(); for(iter; iter < rhs.end(); ++iter) { DeviationValue = (*iter - AVE) * 10.0 / SD + 50.0; rhs.push_back(DeviationValue); }
違います、あの糞コードが面白かったんで真似てる人ですw
accumulate 使って和と二乗和求めてから transform あたりじゃないの?
そんな3パスで
>>360 の1パスに勝てると思ってるのか?
>>360 boost::bindでぐぐるか、(std::tr1::bindがほぼ同じように使える)
関数オブジェクトでぐぐるか。
後者推奨だが。
偏差値を求めるには少なくとも2パス必要じゃなかったっけ
平均と標準偏差は既に求まっている。
要するに3パラメータを持つ関数を取るようなアルゴリズムを教えろと書いてるわけだ。
で、そんなものはないし、標準のbindは2つまでなので正解は
>>365 。
華麗なる回答をいともたやすく繰り出す
>>365 はIT社長かイケメン大学生のどちらか。
関数オブジェクト知ってる人は > 点数、平均点、標準偏差は既に適当なアルゴリズムで求まってます と後出しされた時点でハァ?と思ったわけだが。
っていうか一番最初の質問
>>355 に
>変数が3個あり(点数、平均点、標準偏差)
とずばり書いてあるじゃないか。
点数、平均点、標準偏差を算出しろとはどこにも書いていない。
文章読まない人には永遠に何も作れない。
こういうことけ? struct F { F(double ave, double sd) : ave(ave), sd(sd) {} double operator()(double n) const { return (n - ave) * 10.0 / sd + 50.0; } double ave, sd; }; 〜〜〜 std::vector<double> result; std::transform(src.begin(), src.end(), std::back_inserter(result), F(AVE, SD));
疑問です stl::for_each アルゴリズムですが、イテレータを利用したfor 構文にしか見えないのですが for 構文と比較してoperator() をオーバーロードできるという優位性は認めますが それ以上のメリットはあるのでしょうか?
・タイピング量が場合によっては減るかもしれない ・関数オブジェクトをインライン展開してくれるかもしれない
>>374 どうもです
・タイプ量が減る場合もあるでしょうか、少し複雑な関数オブジェクトなど定義した場合
トータルでは、必ずしも減るというわけではないと、理解しました。
・インライン展開される場合があるとのことですね、それはコンパイラの種類によっても違うのでしょうが
一般的にはどのような条件で、インライン展開されるのでしょうか?
世間一般には、forよりもforeach構文のほうが(ループカウンタが現れない分) 単純(シンプルだったりプリミティブだったり)とされている。 C++のfor文とforeach関数も同様の捉え方をしたらいいと思う。 タイプ量が多いのは今度、その場で関数オブジェクトを書けるようになるラムダ式が入るから、改善される。 (もっとも、そのときにはforeach構文も導入されるけど)
>>376 詳しい解説ありがとうございます
VC8 のfor_each を見ていますが、確かに言われる通りですね、ループカウンタの代わりに、
ポインタをインクリメントしているように見えます(反復子とポインタの正確な違いを理解していないのでごめんなさい)
時々専用template 関数も書いたりしますが、ラムダ式の場合は、やはり私も
for_each 関数、もしくはtransform 関数を使うことが多いですね。
単純に書いたりすると、 for(it = container.begin(); it != container.end(); ++it) { /* something to do */ } ってなったりして end() を毎回呼び出すのかよ!というのを気にしなくて済む。
end() 毎回呼んでも大したことないけどな
お手製のend()や後値インクリメントが万一コスト高かった場合のために、 いちおう普段から、forループではend()呼び出しは一回、必ず前置でインクリメント、 という書き癖を付けてるけど、まぁ「そのお陰で助かった」ということはまだ無いな。
わずかであろうと、わざわざ不要なコストを払うことはないからなあ。 そういうちょっとした積み重ねが、気づかないうちにパフォーマンスの改善に寄与してるかもしれんし。
> そういうちょっとした積み重ねが、気づかないうちにパフォーマンスの改善に寄与してるかもしれんし。 良くこういうことを言う奴がいるが、実際にそういうケースはあったの?
常時心がけていることの積み重ねが生み出すものって、 「はい、これがそうです」と提示できる形にはなっていないものだと思うよ。 プログラミングに限らず。 言うなれば、その人の行うすべての事が、少しずつそのスタンスの影響下にあるわけで、 その一部を切り出して「この範囲内が、私の積み重ねの成果です」とは見せられないと思う。
Premature optimization is the root of all evil.
絶対誰か、この話が最適化の話だと勘違いして その格言出すだろうと思ったw
god hand
この場合やらない意味がないから premature pessimization じゃないの?
一般的処理の応答が0.001秒速くなった所で有り難がる人は果たしているのか?自己満ではないのか?
for文だからな 100万回回せば16分速くなる
>>390 それは、速くするためにコードの読みやすさだの自然さだのを犠牲にする、
「いわゆる最適化」の話。
クヌース先生が、それをあまり初期にやるのは諸悪の根源だと言ってる行為ね
>>385 でも今やってるのは、どっちが読みやすいわけでもないスタイルのうち、
もしかしたら少し速いこともあり得るから私はこっちのほう選んでます、という話。
それはもっとささやかな話で、自己満も何も関係してこない。
どのくらい速いか比べてから決めればいいのに
どっちでもたいして変わらんよ。それがこの話の本質でしょ。
395 :
390 :2009/11/01(日) 23:01:19
>>391 それはメイン処理だな
ユーザーへの応答が、例えばクリック応答が0.001s速くすることに俺は意味を見いだせんね
開発期間が無限に許されているなら、都度書き込ん工数上積みしてゆけばいいんじゃないかな
そこでfor_each関数ですよ。 endが何度も呼ばれることもないし、1度変数に代入する手間も要らない。 ファンクタ作るの面倒?C++0xまでしばしお待ちを……。
>>392 間違いにも程がある。お前はKnuthの論文読んでないな。
We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil. Yet we should not pass up our
opportunities in that critical 3%. A good programmer will not be lulled into
complacency by such reasoning, he will be wise to look carefully at the
critical code; but only after that code has been identified.
It is often a mistake to make a priori judgments about what part of a program
are really critical, since the universal experience of programmers who have
been using measurement tools has been that their intuitive guesses fail.
とあるように、プロファイラも使わずに単なる推測でこっちの方が速かろう
というコードを書くことがpremature optimizationだ。end()のコストを気に
することも同様で、まさに最後の一文に書いてあることの典型例。
それぞれが利点を持ちうる複数の方法があるとき、まず計測する、というのは正しい。 だけど、operator++|--の前置後置や、ループ条件チェックにend()を直接書くか変数に入れるかというのは、 どちらがより良い結果を生みやすいかは自明で「最適化されたら同じになるかもしれない」というだけのこと に過ぎないはずだ。 もちろん、特別な理由で前置が後置よりコストがかかるとか、end()の戻り値を変数に格納するには何か 別のクラスに変換する必要があって、イテレータとそのクラスの比較はend()を直接書くよりコストがかかる、 みたいなのが頻出するようなコードなら話は別だが、これをもって「前置の++/--やend()を変数に入れる のは時期尚早な最適化だ」というのは苦しいし、それこそ「まず計測する」べきことだと思うのだが。
「時期尚早な最不適化」というやつだな 読みやすさも書きやすさも同等のコードで意味もなく遅いかもしれない方を選ぶ理由はない
forでは「条件式内で毎回評価が行われる」を知っておくことは重要だが、 それ以上は、大カッコ{}をどこに書くか に匹敵するぐらい不毛。
だれもパフォーマンスのボトルネックになるから end() を変数に入れなきゃ、 なんて言ってないだろ。最初から。 それなのに何をそんなに食い下がるの? 「ごめん、勘違いしてた」って言いたくないとかいう小学生みたいな理由じゃないの?
>>403 We should forget about small efficiencies, say about 97% of the time:
すら読めないのか?馬鹿にも程があるぞ
>>404 > だれもパフォーマンスのボトルネックになるから end() を変数に入れなきゃ、
> なんて言ってないだろ。最初から。
お前は日本語も読めんのか?
>>405 small efficiencies を読めない程の馬鹿か?
ボトルネックの話なんてしていない
>>406 申し訳ありませんが「パフォーマンスのボトルネックになるから」の部分を
「効率のために」に置き換えて読んでもらえませんでしょうか?
あと、下記の質問について、どのようにお考えでしょうか?
> それなのに何をそんなに食い下がるの?
> 「ごめん、勘違いしてた」って言いたくないとかいう小学生みたいな理由じゃないの?
>>407 自分が勝手に誤解しておいて罵倒とは笑わせるな
> あと、下記の質問について、どのようにお考えでしょうか?
食い下がっているのはお前だw
誰が何を誤解してるの?
誰が何をどう誤解してるの?
盛りあがってまいりました.end();
412 :
デフォルトの名無しさん :2009/11/03(火) 08:55:43
a
効率のためにスタイルを変える話だと勘違いしてる人が 変に絡んでるように見える。
forでなくfor_eachにするメリットの話。 end()云々にそんなに熱くならなくて良い。
std::for_eachアルゴリズムも内部的にループの毎回end()を 参照してる事が多いんじゃないか? ヘッダーファイルを見て見ろよ
>>415 for_each() の中から end() は呼び出せません。
>>416 意味違うって
for_eachをどうやって実現してるかの話をしてるの
>>417 だれもそんな話はしてないが、まぁ話がしたいなら止めはしないでおこう。
誰も言っていないアホな主張を仮定してそれを偉そうに否定する。 最近はそういう遊びでも流行ってんのか?
>>415 for_eachは引数でend()を渡すので、end()を呼ぶ回数は1回だけ。
つまり、効率面ではforループの前にend()を変数に代入するほうと同じ。
クソみたいなオーバーヘッドの塊であるところのSTLで end()ごときの呼び出しコストを気にする意味は全然ない
した、してない の話しだよね
>>422 オーバーヘッドの塊?
例えば何のオーバーヘッドのこと?
例えばvectorなら普通イテレータは唯のポインタだからオーバーヘッド無いよ。 end()呼び出しにはオーバーヘッドあるけど。
>>イテレータは唯のポインタだ 実装依存でしょうが
>427 だから何?
申し訳ありませんが「ポインタだから」の部分を 「ポインタで実装できるから」に置き換えて読んでもらえませんでしょうか? あと、下記の質問について、どのようにお考えでしょうか? > 例えば何のオーバーヘッドのこと?
少なくとも生の配列をfor文で回すよりは絶対に遅い STLは速度と効率を犠牲にして僅かなバカ避けと書きやすさを得るための物であって 速度を気にすること自体が間違い
>>428 だから
>普通イテレータは唯のポインタだから
は間違い。
普通ってなに?
ポインタが普通って初めて聞いたよww
たしか、vcがポインタだから、そう言ってるとしか・・・
> 少なくとも生の配列をfor文で回すよりは絶対に遅い ふむふむ。 > 速度を気にすること自体が間違い 、ミ川川川彡 ,ィr彡'";;;;;;;;;;;;;;; ミ 彡 ,.ィi彡',.=从i、;;;;;;;;;;;; 三 ギ そ 三 ,ィ/イ,r'" .i!li,il i、ミ',:;;;; 三. ャ れ 三 ,. -‐==- 、, /!li/'/ l'' l', ',ヾ,ヽ; 三 グ は 三 ,,__-=ニ三三ニヾヽl!/,_ ,_i 、,,.ィ'=-、_ヾヾ 三 で 三,. ‐ニ三=,==‐ ''' `‐゛j,ェツ''''ー=5r‐ォ、, ヽ 三. 言 ひ 三 .,,__/ . ,' ン′  ̄ 三 っ ょ 三 / i l, 三. て っ 三 ノ ..::.:... ,_ i ! `´' J 三 る と 三 iェァメ`'7rェ、,ー' i }エ=、 三 の し 三 ノ "'  ̄ ! '';;;;;;; 三 か て 三. iヽ,_ン J l 三 !? 三 !し=、 ヽ i ,. 彡 ミ ! "'' `'′ ヽ、,,__,,..,_ィ,..r,',", 彡川川川ミ. l _, , | ` ー、≡=,ン _,,, ヽ、 _,,,,,ィニ三"'" ,,.'ヘ rー‐ ''''''" `, i'''ニ'" ,. -‐'" `/ ヽ ! i´ / ノレ'ー'! / O
>>430 > 少なくとも生の配列をfor文で回すよりは絶対に遅い
ねーよ
なんなんだこのアホは。厚顔無恥にもほどがある。
>「ポインタで実装できるから」に置き換えて読んでもらえませんでしょうか?
「ポインタで実装できる」けど「ポインタで実装してない」場合は?
>あと、下記の質問について、どのようにお考えでしょうか?
>>422 は俺じゃないから関係ない。
俺の環境(Embarcadero RAD Studio 2010)のC++ Builder 2010の std::for_eachの実現方法はループ一回ごとに毎回lastとイテレータを 比較していた Dinkumwareだから多分VC9も同じだろう 安易な推測は禁物だが かと言ってSTLportは既に時代の遺物になっちまったしなあ 速い事は速いんだが
うわっ>< やっぱり安易な推測は禁物だった VC9は同じDinkumwareなのにちゃんとLastの値をコピーして それとイテレータを比較している どんなんやねん Dinkumwareへのお布施の金額が違うのか?
>>438 > 「ポインタで実装できる」けど「ポインタで実装してない」場合は?
普通じゃないな。
>>439-440 > std::for_eachの実現方法はループ一回ごとに毎回lastとイテレータを
> 比較していた
・・・当たり前だろ?
> VC9は同じDinkumwareなのにちゃんとLastの値をコピーして
> それとイテレータを比較している
・・・それで何が違うと思ってるの?
>>442 Lastが遅いと微々たる差だが速度に影響するだろ?
>>443 はぁ?
おまえ C++ 使い始めて何分だよ?
>>444 おっしゃる意味がよくわかりませんが
Cでも同じでしょ
終端条件がもし関数呼び出しになっていて
その関数が大変遅いとどうなる?
つまり for (初期設定; 大変遅い終了条件判定; イテレータ変化) {} となってたらどうなるかって話だよ
>>446 end()とかでしょ
この()って要するに関数呼び出しか関数オブジェクトのどちらかじゃねーの?
速ければいいが遅かったらどうなるよ?って聞いてるの
通常のコンテナで回すのならstart()もend()もメンバ関数だよ 大抵な
>>448 std::for_each() に渡した時点でただのイテレータ型の値だよ。
わからん奴は、effective stl でも読んでろ
何でこんなくだらないことで論争になってるんだ
多分文中に書くfor文と、アルゴリズムを実現するfor文の 意味の違いが微妙なんでそうなってるんではないかと たとえばstd::for_eachがインライン関数になってたら毎回 end()を呼び出す可能性もある
もっとも、ほとんどのコンパイラでfor文を含む関数は
インライン展開されないんだがな
多分
>>456 のようにかえってデメリットがあるからだろう
>>456 ねーよ。
たのむからデタラメを偉そうに書き込むのやめてくれ。
インライン関数であったとしても、endに副作用がある可能性がある以上 1回だけしか評価されないだろ
あーどうしても納得できんわ C言語で終了条件に関数を含むプログラム書いてコンパイルして 吐いたコード見てみる
end()に副作用なんかあるわけないだろ 何をする関数だと思ってるんだ
やってみた 文中に直接終了条件中に関数呼び出しを書いた場合は 毎回関数呼び出しして比較してるな コンパイラによるんだろうけど俺の場合は毎回呼び出していた for_each()は検証できない 俺のコンパイラではfor文を含む関数はインライン展開されないからだ
言葉だけではアレなんでソースも一応貼っとく コメントが入っているfor文の終了判定は毎回関数呼び出しされる int func(void) { int i; for (i = 0; i < 1000000; i++); return 1; } int main(void) { int i; for (i = 0; i != func(); i++); // funcはループ毎に呼び出しされる return 0; }
>コメントが入っているfor文の終了判定は毎回関数呼び出しされる 当たり前
>>465 だからfor_eachのループがもしインライン展開されたらLastも
毎回評価されるでしょって話
>>466 毎回評価されない
お前仮引数を何だと思ってるんだ?
>>466 lastの型がint*とかだったらどうなると思っているわけ?
int nums[] = {1,2,3,4};
for_each(nums, nums+4, 何か関数オブジェクト);
>>467 あ、ちょっと訂正
×毎回評価されない
○毎回評価されるが関数呼び出しは伴わない
iterator last = end(); for( ; iter != last ; ){} とするか for( ; iter != end() ; ){} かだけの違い。 end()が仮に遅い処理だったら、前者の方が良いよねってそれだけ話だと思うが・・・
されるかされないか分からないインライン展開を持ち出すのはどうかと思う
>>470 お前さんの話がそもそも今回話がこじれるようになった発端だぞ
std::for_each()アルゴリズム中で例えfor文が使われていようと、
仮引数で書かれている以上毎回関数呼び出しを伴う事はない
std::for_eachを呼び出す時に一回だけ評価される
後はfor文中のループで毎回その *仮引数* と比較される
わかってる人が誰も説明してあげないので吹いた そして俺も
仮引数だと?
つまりだな for_each(v.begin(), v.end(), func_obj); を呼び出したとき、for_each の引数のLastにはv.end()の戻り値が入るので for_each の中end()が呼ばれることはなくなるはずってところだろ。 インライン展開は関係ない。
>>476 そういう事
>>470 みたいな書きこみが話をややこしくする
文中に書く場合と関数呼び出しで仮引数に書く場合を
はっきり区別しろ
>>477 すまん。てっきり、forの終了条件のところの話しかと思ってた。
for_eachの時の話しだったのか。まじ、すまん。
>>459 ,461 この話に end() には(値の変更と言う意味での)副作用があるかどうかも関係ないね。
結局、for_eachの実装が void for_each(Iter b, Iter e, Func f) { for(Iter tmp=b; tmp != e; tmp++){f(*tmp);} } と void for_each(Iter b, Iter e, Func f) { Iter tmp_end=e; for(Iter tmp=b; tmp != tmp_end; tmp++){f(*tmp);} } のどっちになってるかという実装依存の問題 (細かい作りは本質的じゃないからツッコミ禁止) 前者ならインライン展開されるとend()が毎回呼ばれる ライブラリベンダが気を利かせて後者にしてくれてることを望むしかないわけだが そうしなければならないと強制してくれる物は何もない
コピーのコストとかもあるから上の方が単純に良い訳でもない
下の方が、の間違い
>>480 > 前者ならインライン展開されるとend()が毎回呼ばれる
ねーよ。
>>480 おねがいですから、もうやめてください。
>>480 >前者ならインライン展開されるとend()が毎回呼ばれる
また馬鹿が現れた
これ関数よ?end()は既に仮引数に化けてるの!
>>483 じゃあ、どうなると思うの?
前者で書いてもコンパイラが最適化で勝手に後者に変えてくれると思ってるなら
ちょっと期待しすぎだと思う
っていうか同じ人でしょ? 今時こんなのが1日に何人も現れるわけがない。
しかし、やっとfor_eachを持ち出すわけが分かった。
>>480 #defineではあるまいし、前者をインライン展開した結果endが複数回呼ばれるコードが吐かれるわけがない。
もし、そんなコードを吐くコンパイラがあったら、それは規格に反している。
(endの中に副作用がないなら話は別だが)
>>485 「インライン展開されると」を見落とさないでくれ
普通の関数ならもちろん呼び出しは1回だよ
eという名前でスタックにend()のコピーが積まれるからね
>>486 いい加減に関数について基本から勉強しなおしてください
お願いです
>>486 int f();
void g(int x);
int main() { g(f()); }
お前はこのプログラムで f() が何回実行されるか g() の中身がわからないと定まらない、と、
そう言うのかね?
>>489 インライン展開は無視する事ができる
という事は、インライン展開されようとされまいと全く同じ
動作をするコードをコンパイラは吐かなければならないわけ
わかる?
>>490 アウトライン関数とインライン関数の違いについて勉強してください……
>>491 gが
inline void g(int x);
だったら当然gの中身を見ないと何回呼ばれるかはわからない
でも中身はヘッダにあるはずだから書いたときに判断付くでしょう
>>493 今度は「アウトライン関数」という造語ですか?
>>494 > だったら当然gの中身を見ないと何回呼ばれるかはわからない
さんざん違うっていわれてるのに、なんで当然なの?何が根拠なの?
>>492 だから、インライン関数の引数に代入文やインクリメントを入れるのがまずいんだよ
意味変わっちゃうから
>>497 誰も今そんな話はしてないだろ
話を逸らすなカス
別に普通の言葉だと思うが>アウトライン関数 気に食わないなら非インライン関数でも逆インライン関数でもなんでもいいよ 問題はそこじゃない
>>497 インライン関数はプリプロセッサマクロとは違い、そのような注意事項は無用です。
>>499 あのね、
>>492 でも書いたけど、インライン展開の指令を
コンパイラは無視していいわけ
だからインライン展開すると意味が変わってしまうようなコードを
コンパイラは吐いちゃいけないんだよ
>>501 その通り
だからプログラマもインライン展開すると意味が変わってしまうようなコードを書いてはいけないんだよ
>>502 (゚Д゚ )ハァ?これ以上付き合いきれんわ
馬鹿過ぎ
お前もう寝ろ
>>501 そうだから、意味が変わらないようにインライン展開してくれるのが、
インライン関数の優れているところだとinlineができた当初から言われ続けている。
>>502 あなたにそのように教えた本や人やサイトを教えてもらえませんか?
潰しにいくから。
やれやれだ
インラインの細かい実装は今はどうでもいいよ
話を元に戻そうぜ
実装が
>>480 の前者だったら
for_each(v.begin(),v.end(),f);
のインライン展開はこうなるだろ?
(最適化で追い出してくれるかもしれないという話は考えないとして)
for(Iter tmp=v.begin(); tmp != v.end(); tmp++){f(*tmp);}
条件節にv.end()が現れてるのが見える?
>>505 > のインライン展開はこうなるだろ?
なりません。
508 :
デフォルトの名無しさん :2009/11/04(水) 00:36:09
506 釣りだと言ってくれ
509 :
507 :2009/11/04(水) 00:37:22
ごめんアンカーミスった。
× 505 ○
>>506
強情だな じゃあどうなるっていうんだ 書いて見せろよ 当然だが、最適化でv.end()の戻り値を保存する変数を追加してくれるかどうかは コンパイラの質次第だから当てにしないという前提でな
>>506 だ か ら
インライン展開してそのようなコードを吐くなら
インライン展開する場合としない場合で意味が変わってしまうでしょ?
だからそういう展開はしない事になってるの
>>506 /: : : : : __: :/: : ::/: : ://: : :/l::|: : :i: :l: : :ヽ: : :丶: : 丶ヾ ___
/;,, : : : //::/: : 7l,;:≠-::/: : / .l::|: : :l: :|;,,;!: : :!l: : :i: : : :|: : ::、 / ヽ
/ヽヽ: ://: :!:,X~::|: /;,,;,/: :/ リ!: ::/ノ l`ヽl !: : |: : : :l: :l: リ / そ そ お \
/: : ヽヾ/: : l/::l |/|||llllヾ,、 / |: :/ , -==、 l\:::|: : : :|i: | / う う 前 |
. /: : : //ヾ ; :|!: イ、||ll|||||::|| ノノ イ|||||||ヾ、 |: ::|!: : イ: ::|/ な 思 が
/: : ://: : :ヽソ::ヽl |{ i||ll"ン ´ i| l|||l"l `|: /|: : /'!/l ん う
∠: : : ~: : : : : : : :丶ゝ-―- , ー=z_ソ |/ ハメ;, :: ::|. だ ん
i|::ハ: : : : : : : : : : : 、ヘヘヘヘ 、 ヘヘヘヘヘ /: : : : : \,|. ろ な
|!l |: : : : : : : : :、: ::\ 、-―-, / : : :丶;,,;,:ミヽ う ら
丶: :ハ、lヽ: :ヽ: : ::\__ `~ " /: : ト; lヽ) ゝ
レ `| `、l`、>=ニ´ , _´ : :} ` /
,,、r"^~´"''''"t-`r、 _ -、 ´ヽノ \ノ / お ・
,;'~ _r-- 、__ ~f、_>'、_ | で 前 ・
f~ ,;" ~"t___ ミ、 ^'t | は ん ・
," ,~ ヾ~'-、__ ミ_ξ丶 | な 中 ・
;' ,イ .. ヽ_ ヾ、0ヽ丶 l /
( ;":: |: :: .. .`, ヾ 丶 ! \____/
;;;; :: 入:: :: :: l`ー-、 )l ヾ 丶
"~、ソ:: :い:: : \_ ノ , ヾ 丶
>>510 >当然だが、最適化でv.end()の戻り値を保存する変数を追加してくれるかどうかは
>コンパイラの質次第だから当てにしないという前提でな
精神科逝け
>>511 だからさ
インライン展開するしないで意味が変わったら困る、それはその通りだ
だがプログラマがそうならないように気をつけることと、
賢いコンパイラがそうならないように気を遣う事は別の話だ
君はそれがごっちゃになってる
>>510 お前のほうこそ、引数にある関数呼び出しを関数の中で繰り返し行うような関数をひとつでも
書いて見せろ。あ、報告はもちろん手元でアセンブリ見て確認してからな。
>>514 お前こそマクロとインライン展開をごっちゃにしてるじゃないか
もうやだ。絶対釣りだろ、これ。
>>516 マクロとインライン関数は全然別物だよ
インライン関数は型チェックが働くしオーバーロードも出来る
だが今の話には関係ない
>>518 何言ってるんだ
今の話に関係おおありだよバカ
>>510 > 当然だが、最適化でv.end()の戻り値を保存する変数を追加してくれるかどうかは
すでにコード中に e (
>>480 ) という変数があるんだが。
約一名だけが、この変数が(なぜか)除去されると主張している。
またすごいやつが現れたもんだ
もう面倒臭いから、文句付けてる人らは 506のインライン展開がどうなると主張したいのか、書いて見せてくれよ 最適化抜きでな 何が言いたいのかさっぱりわからない
この勘違いぶりにはある意味尊敬を覚えるよな本当に インライン関数を完全に誤解している
>>510 > コンパイラの質次第
一応、可能性としては主に次の2つが考えられる。
1. v.end()の戻り値を保存する変数を追加する
2. インライン展開しない
だがしかし、
3. v.end()を毎回呼ぶように展開する(for(Iter tmp=v.begin(); tmp != v.end(); tmp++){f(*tmp);}のように)
これはない。
>>520 eは(bもfもだけど)アウトライン関数ではスタック変数になるけど
インライン関数では展開時に置き換わって消えちゃうでしょ
わかる?
>>522 // for_each(v.begin(),v.end(),f);
{
Iter b(v.begin());
Iter e(v.end());
Func f(/*outer*/f);
for(Iter tmp=b; tmp != e; tmp++){f(*tmp);}
}
>>525 だから消えるか消えないかはコンパイラ次第だが
スタック変数と全く同じ動作をするコードを吐く
毎回end()を呼ぶようなコードは絶対に吐かない
スレが突然増えてるなと思ったら・・・まあいいや。寝よ。
>>526 に限らず、一つ言えるのは
「お前らコンパイラの最適化に期待しすぎ」
forを検知したら条件節で使われる関数呼び出しを自動でキャッシュしてくれたら
まあ便利だろうけど全てのコンパイラにそれを望むのは酷だ
そんなことしてくれなくても効率良く正しく動くように書くのが正しい
あーもう馬鹿らしくなってきた ぜってー釣りだなこれ
>>529 変数を除去してくれちゃう最適化(だかなんだかわからん困った変形)は前提にしていいのかw
最近のアイちゃんは賢いな。
>>529 それができないコンパイラはインライン展開しないという選択肢を取る。
>>529 挙動が変わるのはコンパイラの最適化とは言わない。
int f(){
cout << "Hello world" << endl;
return 1;
}
void g(int i);
int main(){
g(f());
}
関数gの実装によってHello worldが表示される回数が変わる仕様なわけがない。
最適化は絶対に挙動を変えないと思ってる男の人って…… inlineを付けた関数で副作用を何回も起こさないように気をつけるのはプログラマの責任 付けてない関数を副作用が繰り返されないと判断してインラインにするのは 賢いコンパイラのアグレッシブな最適化の一つ やっぱりごっちゃになってる
>>534 念のため、inline void g(int i) {/* 〜 */}となどと書いておくべきだったと思う。
もちろん、標準規格に合致した普通のコンパイラなら結果は変わらないけどさ。
これほど実りのない議論も最近珍しい
議論じゃないだろこれ 完全に文法を誤解しているのか知っててわざと釣りをしているのか 知らないけど、とにかく相手をいらだたせるような話の方向に持って 行こうとする まるで「私がC++コンパイラです」みたいな間違い方 最悪だ
「こういうことになってる」と「こうあるべき」が混ざってる人とは どうにも話が噛み合わないね
ここまでで得たもの 0 …いや、NULLと言った方がいいか?w
>>541 NULLはまだしも使い道があるが・・・(ガッしたりとか)
帰省中で閑散としてる2chで このスレだけえらい伸びてると思ったんだが 一人で引っ張ってるアホがいるのか
ああ、彼は今お眠りになられているので静かだが 間もなく目お開きになられ、そしてそのありがたいお言葉を とうとうと述べられるのです
>>535 謙虚に冷静に聞いて欲しい.
いいかい?
あるアプリケーションのすべての関数にinlineを明示しても,
そのアプリケーションの意味論は変化しない.
コンパイラが生成するバイナリは変化する可能性がある.
もう一度言うよ.
バイナリが変化して実行速度が変化することはあるが,意味論は変化しない.
意味論は変化しないんだ.
で,だ.
この話はアセンブリまで見る必要ないよ.
実際にinlineの有無で挙動が変化する例をコンパイラとコードを明示して僕らに教えてよ.
僕らはそんなコンパイラは存在しないと主張しているので動く証拠を見せられるのは君だけだ.
inline void f(int x) { /* ここをどうにか */ } int g() { return puts("Hello"); } int main() { f(g()); return 0; } f() の中身をどうにかするだけで "Hello" を2回表示させることができるというわけだな。 さぁやってみせてもらおうか。
haskellうひっっ
template class を継承するメリット、デメリットについてどう思われますか? 自分はfriend 関数を、止むおえず使わないといけないような(friend を使うことによって可読性や構成がすっきりするという意味合いです)、 限定的なクラスデザイン以外に、継承を使うメリットは無いように思うのですが・・・・ 使用するにあたっても、書式がコンパイラ依存する部分も多々あり、使いにくい印象もあります いかがなものでしょうか?
>>548 普通の継承と同じようにメリット・デメリット(や妥当性)を考えればいいんじゃないの?
なんでテンプレート限定で考えてるの?
friend との関係もわからないし。(日本語的な問題も含めて)
>>549 thx です、なるほど解りました。
friend関数については、忘れてください混乱してました。
4連休明けに見に来てみれば面白いことになってたんだな・・・ 完全に釣られてる側の負けだろこれ
たぶん途中で間違ってる事に気づいて釣りに切り替えたんじゃないかと・・・。 どっちにしろ反応してもいい事はないけどね。
>>545 意味論は変化しなくても、副作用は変化するかもしれない
例えばコピーコンストラクタに何かの処理を入れたクラスは
それを返す関数でRVOが働くかどうかによって挙動が変わるよな
値戻しという意味論は変わらなくても、実際の処理は最適化によっていくらでも変わりうる
>>546 簡単なのはこれ
inline void f(int x) { x;x; }
ただし最適化によって一時変数が追加されるかもしれないし、丸ごと消されるかもしれない
(intの評価に副作用がないのは明らかだから)
VCとGCCで最適化切って試してみたらどっちも1回だったな
今時の立派なコンパイラはこれくらいデフォでやっちゃうのかもしれない
しかし全てのコンパイラがそうしてくれる保証はない
山田君、例のもの(規格書)持ってきて。
>>553 あなたのオレオレ規格はわかりました。
あなたがそれをどこで知ったのか、
その根拠を教えてください。
あるいは、
>しかし全てのコンパイラがそうしてくれる保証はない
そうしてくれないコンパイラをたった
ひとつ教えてくれるだけでもいいです。
>>373 です
for_each の存在自体に疑問を感じて質問した次第です、その流れでこの度の最適化の議論にいたっているわけですが
実はそこが、知りたかった部分でもあります
最近この言語の深淵を感じるに、皆様方には周知の通りかと思うのですが
C/C++ の長所として、変数という定義において、即値と参照という二つのパラダイムがあるわけです、
しかしこれが逆に、この言語を難解にし、時代の変化を全て受け入れるがごとく、仕様とあいまって複雑にしているのではないかと感じている次第です。
>>553 じゃあこう書いたら、g()は一度も呼ばれないわけか?
inline void f(int x) { }
>>555 普通のC++98ですけど……
インラインの意味は7.1.2に書いてるな
で、当たり前だけど出来る限りアグレッシブに最適化しろだの何だのとは書いてない
そっちこそどの辺が根拠なの?
>>557 インライン展開されればそうだよ
>>556 for_eachは気に入るか気に入らないかで使うかどうか判断していいレベルの物だと思う。
個人的には関数オブジェクト書くのが面倒なだけで使いたいと思わない。
forかboost::foreachを使う。
>>558 色々と小細工しているから釣りにしか見えないんだけど。
釣りじゃないなら、>553や>557をちゃんと検証してご覧よ。
>>553 にも書いたけどVCとGCCで検証したぞ
どっちも最適化かかっちゃうらしくて1回になったけど
こいつらが賢すぎるだけだと思う
>>557 も試してないけど多分1回だ
というか、そんなことはどうでもいいけど
どうしてそんなに、されるかどうかもわからない最適化に依存しきった話を
自信満々にそうなるはずだと言い切っちゃえるのかね?
コンパイラを常に完璧な最適化をする神様か何かと勘違いしてない?
あ、他のコンパイラは手元にないです 誰か試して
されるかどうかもわからないものでもなければ, 最適化でさえないからだよ〜
565 :
564 :2009/11/04(水) 19:46:01
あ、ごめん
混乱してたわ
> 最適化かからないんなら
>>553 は 2 回のはずだよね?
これは間違いだ
インライン関数fの実引数にインライン関数gの戻り値を指定した時、 fにgの実装がそのまま渡されるとするなら、fの仮引数の型とgの戻り値の型は一体なんなんだ? 型安全のある言語でそんな仕様考えられない。
最適化で結果が変わるコンパイラなんてない。 # 精度的な問題を除く。 インライン展開を何だと思っているんだろう……
お前らまだやってるのかw いい加減にスルーしろよw
俺の中では
>>373 が何を勘違いしてるか理解できた。
規格書の1.9に >When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of >all function arguments (if any) which takes place before execution of any expressions or statements in the >function body. There is also a sequence point after the copying of a returned value and before the execution of >any expressions outside the function. とあるので、関数がインラインかどうかに関わらず、実引数の評価は関数本体の式または 文の実行に先行する。つまり、関数の内側がどうなっていようと評価回数は変わらない。 1.9には他にも、実行結果は抽象機械の実行結果と等しくなければならない、と定めてあ るから、この点でも、最適化によってインライン関数の挙動が異なりうる、という主張は正 しくない。
>>570 でかした
後は妄想野郎が難癖を付けてきてもスルーな
当たり前の話だろ。インライン化を含む最適化 でそんなところの挙動が変わったら、それは コンパイラのバグだから。
誰もスレチと言い出さない優しさに泣いた
スレチか否かはさておいて、いろいろ勉強にはなった。
for_eachをお題にしたこの話、世間的には min maxマクロの危険性と、<algorithm>内にあるmin max関数の件で さっさと通り過ぎるものだよね。 一人で頑張ってる人は、min max関数にも、min maxマクロのあの min(f(), g()); とかの危険があり得るという考えなわけだ。 そうならないのは、コンパイラが機転を利かせているからに過ぎないと。
スレチかも知れないが見ている分には楽しいからもっとやれ
ごめんなさい 規格で必須の最適化だったとは知らなんだ でも、これってつまりどんなに単純なC++コンパイラでも、インライン関数では必ずforを探して 使われてれば引数をキャッシュする最適化をやれと言ってるわけだよな なんだかなぁ
それがfor文を含む関数のインライン化を拒否するコンパイラが多い理由
だから最適化じゃないし、forも関係ないって。 極論だがシンタックスシュガーのほうが近い。 わざわざ Iter b(v.begin()); Iter e(v.end()); for_each(b, e, f); と書かなくてもいいことを規格で保証しているだけ。
>>578 ループを含む関数のような処理時間のかかる関数はインライン展開しても効果が薄いってのもあるけどな。
>>577-578 579 も言ってるが
>>526 のような展開は最適化の結果でもなんでもなく、
最も素直なインライン展開の実装。
わざわざ
>>506 のような奇妙な式の移動を行う必要はまったく無い。
for があることでインライン展開されなくなることはあるだろうが、それはまったく別の理由。
多分、最適化のこともインラインのことも勘違いしてるんだろうね。
インライン展開とは、関数を実行したのと同じ「意味」になる処理を呼び出し側に埋め込んで
関数呼び出しのコストを無くすことであって、
「意味」を変えないためには
>>526 のようなことが必要になる。
これは最低限の自分の存在理由を満たしているだけであって、「最適化」などではない。
一方、彼の考えるインライン展開は、引数として渡した「記述」を切り貼りして
コードの姿を組み立てて、それを呼び出し元に貼り付ける、というような物らしい。
でも、それはマクロがやってることだ。
マクロといえば、簡易的なLisp処理系を作って、強力と名高いLispのマクロを実装してみると、
このへん勉強になるかもね。
Lispの言葉でいうなら、C++の関数は「引数はすべて評価してから関数に渡される」。
つまり f(g(), h());の時、fが受け取る(そして扱う)のは「g()の戻り値」と「h()の戻り値」。
だからインライン展開するにあたって、
>>526 のようにすることでそれを実現する。
それに対して、Lispのマクロは「引数を評価せずに渡し、戻り値で呼び出し側を置き換える」。
こっちが彼の考えるインライン展開に近い。
インライン関数とマクロについて完全に理解できてない子って前から分かってんのに、スレ伸びすぎだろw
彼は今寝てるの?
>>577 > でも、これってつまりどんなに単純なC++コンパイラでも、インライン関数では必ずforを探して
> 使われてれば引数をキャッシュする最適化をやれと言ってるわけだよな
インラインであろうと無かろうと、関数内にforがあろうとなかろうと、引数は全てキャッシュ(というか一時変数への保存?が)される。
それがC言語からの関数呼び出し構文の意味。
わざわざforを探す必要はない。常にそういうコードを生成すればいい。
>>570 によれば引数の評価は関数の実行より先にしなければならないのだから、
評価した結果を(実際に使われるまでの間)どこかに取っておかなければならないことは必然。
ループの中で毎回評価するようなことは以ての外。
>>582 Lispの話は蛇足。
自分が言いたいだけだろ…。
おまいらちゃんと指摘してやれよ。 ・値渡しと名前渡しをごっちゃにしちゃいかんよ。 C++に名前渡しは無い。インラインだろうが値渡しとして処理される。 ・仮引数と実引数をごっちゃにするな。 関数呼び出しに関係するのは実引数の方。 ・値渡しは関数を呼び出す前に一度だけ評価される。
そっとしとこうぜ 知ったかは何か書くことで満足を得ている人種なんだから・・・
>>588-589 知らないなら調べればいいじゃん。恥ずかしい子達だな。っていうか一人かな。
C++しか知らない世間知らずはこれだから
まぁしかし、WikiぺによるとほぼALGOL限定の機能らしいので そこまで知っていろというのも酷かと^^ しらべりゃいーじゃんというのには同意だがw
なんでALGOLの話が出てくるの? ここはSTLのスレだからC++の話でしょうに
おおざっぱにいえば f(1+1) でfに1+1がわたるか2がわたるかだよね 1+1がわたるのは遅延評価/非正格とかの場合、Haskellが有名 C++は多くの言語と同じように、正格で遅延評価を行わない言語 つまり実引数は関数呼び出しの前に評価され、関数fには2が渡る これはインライン関数でも同じ でもこれってインライン関数を習うときにまっさきに知るようなことでないの インライン関数はふつうの関数と同じようにつかえて、マクロみたいに実引数が 意図せず複数回評価されたりする危険性がないのがウリですってさ
ではHaskellは非効率なのかといえばそうではなくて
ひつようがなければそもそも実引数を評価しないし
同じ引数はmemoizeして何度も不要な評価をしないようにしているのだと思った
>>587 がALGOLのcall by nameを持ち出しているのは、1+1を渡して
かつ非効率なものの例なんだとおもう
Haskellのはcall by needとかいうんだよね
まあよくしらんけどw
>588,>593 調べる努力ぐらいしようぜ。昔みたいに本読まなきゃ情報得られない時代でもないんだからよ。 ゆとり教育はそういった努力を教える仕組みだったはずなんだがなぁ…… 細かいところは>594-595の言う通りですな。 インライン関数だとしても呼び出し元からすれば普通の関数と同じように見える。
>>596 だからなんでスレ違いの話をするのかって聞いてるの
598 :
587 :2009/11/07(土) 13:46:35
わははははははははははははは。ナイスジョーク。 上のぐだぐだのコメントも理解力の足らない間抜けが引っ掻きまわしているだけだし、 最近のコメントは全部スレ違いなんだろうね。
スレ違いスレ違いって引っ張ってるバカが黙れば このやりとりは終わるんだよボケが
601 :
587 :2009/11/07(土) 14:23:28
602 :
デフォルトの名無しさん :2009/11/07(土) 16:03:30
なぜかとくいげ
去年の暮れからこの板の民度が落ちているのは 派遣切りにあったITドカタと 最初から働く気のないニートがせめぎあっているからですね?^^
主張さえ正しければどのようなレスをしてもいいと思ってる
>>601 がウザいんですけど
インライン最適化の話はもういいよ ここはSTLのスレだぜ
>>604 ムカついたから厳格になって閉め出してやれ、って感じ?
まず、言語の話ですらない感情論全開の自分のレスに厳格になれよ。
>>601 その文を読んで誰が得するのか
>506が読むとなんか変わるのか
もう一度考えてから氏ね
>>607 お前のそのレスでしょ? 誰も得しないし何も変わらないのは。
なんで明後日の方向にズレてるばかりか、自分にだけ寛大なの?
規制が解除されると途端に変なのが一杯湧いてきたな
えーとこの話題が始まったのどのへんからだっけ?300ぐらいだっけ?長いなぁ。
もう、Efficient C++とEffective STLを読んどけでいいだろう。
C++初心者から質問です。 STLというかC++ってどうやって関数の仕様調べるんだろ? Cだとprintf調べたいとき、man printfってやれば すぐに出るけど、C++でcoutとか調べたいとき 手元に本かネットがないとつらい。 みんなどうしてるんだ?ヘッダー見てるの? ちなみにLinuxなのでMSDNはなしです。
manのようなことがしたいならcpprefを使ってみたら
>>612 ISO/IEC 14882/2003 または JISCX3014
>>613 perlと格闘してようやくインストールできた。
こんなのが欲しかったんよ
ていうか、perlってこんなことが簡単にできることに驚いた。
>>614 JISはダウンロードして閲覧できないんだな。。。
言語仕様とか調べるときはよさそう。
>>615 昔は出来たんだがなごにょごにょすれば
でもどちらにしろ漢字コードではなくて単なるビットマップなので
検索が出来なくて非常に不便
>>616 検索できるはずだよ
ただしひらがなカタカナ漢字のみ。英数字はダメ
cppref知らんかったわ。俺からもありがとう もうsgi accumulateとかしなくて済むのか
vectorのテンプレートみてたら、beginなどの戻り値がteratorでそれをvectorのiteratorのコピーコンストラクター 初期化するとiteratorの中にiteratorのある構造になってしまうとおもうんですが。 それでいいんですか?
> それをvectorのiteratorのコピーコンストラクター初期化するとiteratorの中にiteratorのある構造になってしまう もう少し日本語でおk
その程度の読解力もないのなら洋書はよめませんね。
洋書なら読めるだろう。こんないかれた文法にはなってないだろうし。 >vectorのiteratorのコピーコンストラクター 「イテレータを引数にとる vector のコンストラクタ」 ではなさそうだな。何だろう…
ヒント: vector::iterator=vector.begin();
vector::iterator i(v.begin()); ? iの中にイテレータそのものが入るのではなくiの各メンバ変数にv.begin()のメンバ変数がコピーされるだけだが。
イテレーターそのものが入るよ? ポインターの場合はメンバー変数が無い場合もあるからね。
>>627 そういう意味でなら
> iteratorの中にiteratorのある構造
も当たり前のことをいってるだけだな。
そうじゃなくて、ポインターもイテレーターも区別せずにイテレーターのデータに代入される。
ある本にvectorのイテレーターはポインターだ、と書いてあったからソース見てみたら ポインターじゃなかった。いつから変わったんだろうか。
そんな事言われても動作があってればポインタかどうかは処理系依存だし
>>630 その本はいますぐ燃やしてください。^^
規格票にはvectorのイテレータがポインタでなければならないとは書いてないし
Effective C++にもそうじゃないケースがあるよって書いてます。
あ、Effective C++じゃなくて、Effective STLの方だったかな? あと、本を燃やす前に本の名前と著者をさらしてくれると 二度と一生その人の著書を読まなくてすむので助かります^^
うん。それは本が悪いんじゃなくて、君がバカなだけ。
本を燃やせと言ったくせに・・・・・
だって、その本は親切にも日本語版が出ていて 日本語版にはそんなアホな記述ないもの。 つまり、君が英語読めてないだけ。
実装例の話だが、VC++2008だとvector::iteratorはポインタではないね。 ポインタ扱いにして高速化する指令方法があったような気もするが
>>637 ストリングとベクトルはポインターを返すから一時変数に++は使えないと書いてある。
本ではなくあなたを燃やしてください^^
本の作者にいってください^^
>>639 もしかして、俺が英語を読み取れてないのかも。
該当箇所を引用してもらってよいですか?
>>638 C++ Builderだと6まではポインタだった。2006になってポインタじゃなくなった。
6まではSTLがSTLPortだったのが,2006からdinkumware製になって実装が変わったから。
いずれにしろポインタであることを期待してコーディングするのはまずいと思う。
速度最適化オプションと-DNDEBUGつけてもポインタにならないの?
最適化したら、ポインタではないものがポインタになっちゃったりすると 非常に困ることになるんじゃないでしょうか。
少なくともvectorでは困らないよ。 なぜなら、vectorのイテレータはランダムアクセスイテレータとして扱わなければならず そう扱っている限り、それがクラスでもポインタでも同じだから。
困るようなケースではなっちゃたりしないけどな。
VC9ではポインタになるな
実装依存の話は実装依存スレで!
&*i でポインタは得られるな
TR1 だと data() でポインタを得られたような
>>655 日本語でそこそこわかりやすかったのに残念。
658 :
デフォルトの名無しさん :2009/12/03(木) 11:37:19
見てないけどrbeginとrend用?
>>658 リンク先は見てないけど
規格上、長さnの配列aに対してa[n]へのポインタ値(a+n)を扱うのは問題ないです
ただし、そのポインタの参照はがし(*(a+n)とかa[n])はできません
ありがとうございます。
見てないけど、礼にはおよばねーぜ
&a[n] もやっぱりエラー? aがoverload されてない組み込み型だったときでも エラーになるか &a[n] !=(a+n)となる可能性は規格的に起こりうる?
>>665 その場合&a[n]は&*(a + n)と同一視されて、このような式は(a+n)に置き換えられることが規定されてる
>>666 「規定されてる」っていうと、 C++ 標準規格で?
該当箇所を挙げてもらえますか?
vectorのメモリ連続性が保証されているということは、 普通の配列を渡すような場面で使っても問題はないのでしょうか? たとえば以下のような例です Point pt = { 0, 0 }; //struct Point { int x, y; } std::vector<Point> v; v.push_back(pt); memcpy(buffer, &v[0], v.size()*sizeof(Point));
ok
>>668 その理解で問題ない。
ただ、注意点としてvのsizeが0のとき
&v[0]は不正だからそのチェックだけ忘れずに
コンテナの使い分けってどうすればいいんですか? ランダムアクセスが不要な場合は list を使えばいいとして vector と deque の使いわけがよく分かりません 色々なソースを見ると、vector の使用頻度が高いように思えるのですが 要素の追加で再配置しなくていい分 deque の方がいいんじゃないですか?
dequeだとブロックで扱えないので、そこが使い分けるポイントかな。
>>672 deque には vector には無い空間オーバーヘッドと速度オーバーヘッドがある。
vector で済むところに使えば無駄になることもある。
どちらが大きな問題になりやすいかと言えば vector の再配置だろうから、
ランダムアクセスコンテナとして deque を優先的に使うという話には一理ある。
>>673-674 大きさを指定し、あまり拡張のない場合は vector の方がパフォーマンスがいいということですか
ありがとうございます、1つの基準にします
入門書がだいたいvectorで始まるもんで、dequeのほうがいい場面でもvector使っちゃう人が初心者には多いような ・・・上級者にも多いとは言わないよね
dequeが意外と遅い場合もあってポインタのvectorですませちゃうな。 要素の追加も大抵上限や要素数わかってたりするからreserveで十分だし。
本当にどっちでもいいならvectorを使うだろう。わざわざ複雑な方を使うこともない。 でもコンテナの使用頻度的にはvector>deque>listかな。listが要る場合ってほとんどない。
シーケンシャルアクセル: list > vector > deque ランダムアクセス: vector > deque 追加: list > vector > deque 追加(サイズ変): list > deque > vector この認識であってる?
シーケンシャルは vector > list なのでは?
>>679 シーケンシャルアクセル:
vector > deque >> list
ランダムアクセス:
vector > deque
追加:先頭:キャパシティ変更なし
list > deque >>> vector
追加:先頭:キャパシティ変更
list > deque >>> vector
追加(サイズ変):
list > deque > vector
>
> この認識であってる?
すまん、途中で送信しちゃった。
とにかく参照はvector最強、でいいよ。
>>679 こうじゃない?
シーケンシャルアクセス:
vector > deque >> list
ランダムアクセス:
vector > deque >>> list
挿入:先頭:キャパシティ変更なし
deque > list >>>> vector
挿入:先頭:キャパシティ変更あり
list >> deque >>>> vector
挿入:中間:キャパシティ変更なし
list >>> vector > deque
挿入:中間:キャパシティ変更あり
list >>>> vector > deque
挿入:末尾:キャパシティ変更なし
vector > deque > list
挿入:末尾:キャパシティ変更あり
list >> deque >>>> vector
不等号並べて書いちゃう男の人って・・・
こうやって見ると、deque の使い所がいまいち……。 メモリ効率を度外視し、vector をほぼ固定配列として使える場合、 vector でなく deque にしかできないこと、使う理由ってありますか?
dequeは名前の通りキューとしてだけ使えばおk
>>684 いろいろ間違ってるだろ。
dequeはオブジェクトのメモリ領域がエレメント複数個をまとめてアロケートされるからvectorのキャパシティ変更に関わらず
挿入:先頭
list > deque >>>> vector
挿入:末尾
vector > deque >= list
挿入:末尾:キャパシティ変更あり
list >= deque >>>> vector
だしdequeは全てのエレメントが連続しているわけじゃないから実際には
挿入:中間
list > deque > vecto
しかも「キャパシティ変更」の有無でvector以外のクラスの順位が変わるのも変。
知ったかぶりはやめろ。
dequeは末尾・先頭への追加に限れば、メモリ拡張の必要がある時にも 既存の要素のコピーが発生せず、参照やポインタも無効化されない。 これは大きな利点だと思う。
deque<bool>はコンテナ用件を満たすけど vector<bool>は満たさないという問題も。 速度に関しては実測せよとアレに書いてあったじゃろ? そして、自信を持ってvectorを選択せよ、とも。 アレが何かわからない人には教えてあげません^^
[ vector ] [ ][ deque ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ] list こういうことですか deque はリストと同じような構造だと思ってました
dequeはVCだと要素数2の配列がlist構造だね。 他の処理系は知らん。
両刀マッチョ行列
>>688 listの挿入はメモリ確保が生じるからキャパシティに余裕があるvector,dequeに対しては
挿入:先頭:キャパシティ変更なし
deque > list >>>> vector
挿入:末尾:キャパシティ変更なし
vector = deque > list
でいいだろ。
いやいやいや deque は、”一般的な利用”においては、vectorに比べ圧倒的に速いぞ。 極論言えば、むしろvectorがいらんぐらいだ。 vectorの利点はmemcpy()が使えるぐらいのもんだ
その”一般的な利用”とかいうのはどんな統計的手法に基づいて評価されたものなのだ。 ちゃんとソースを出すのだ。 ここは文系のカスプログラマが思い込みでクソ垂れる場所じゃないんで。
たかだかコレクションの実装について速いだの遅いだの言ってるお前らがカワイイよ。
おおまかな使い分けについては規格に書いてあるよ 特に(dequeやlistを使う)理由がないときはvector 先頭末尾への挿入削除が多い場合はdeque 中間への挿入削除が多い場合はlist だった気がする
確か過去スレでdeque vs vectorの議論あったな
いやいや圧倒的に速いならdeque使うしかないだろ
お前らのアプリはコレクションに支配されてんの? 実行時間の80%はこれらをソートしたりナメたり入れたり出したりしてんの?
>>701 vectorからdeque へのtypedef書き加えるだけでも、多くのケースで体感スピード上がるという話
>>702 英語は読めないのでエスペラント語でお願いします。
vectorはメモリの連続性が真に必要なときと1バイトでもメモリ使用量を減らしたいときにだけ使え。
エスペラントなんて欧米の一部言語学保守派しか使ってないだろ
10000件近い固定サイズ構造体をdequeで使ってたんだが、boost::poolのアロケータ組み込んだら 計測値で1.7倍程度速くなった。 アルゴリズム以前にアロケータでのメモリ確保処理の速度も考えたほうがよさげ (vectorではこうはいかない)
ちょっと書き方が不足してた 10000件近いデータを、数百〜数千件単位で頻繁に挿入・削除してるという使い方。
>>707 それはとくにdequeが適する
場合なのでは?
万能コンテナなんか存在しない、
使い分けが大切、でFA。
>>706 日本語なんて極東の小さな島国でしか使われていませんよ?
それのせいでコンピュータ関連の書籍が
日本語になるのは世界から1,2年遅れていて、
プログラマになったばかりの小学6年生が学習書にも困る有様です。
まったく持ってIT後進国です。
誰も万能、って話をしていない現実w
>>705 >1バイトでもメモリ使用量を減らしたい
フラグメを考えると、使用量は逆に
意外と増えがち。
vectorのオススメは
○reserve()できるとき。
○挿入が少なく、参照が多いとき。
だろう。
そういったケースだと、 vector<CLS*>かdeque<CLS*>かlist<CLS*>の方がよさげ 構造体をまるまる挿入するのが負荷が掛かるから。
listはlist同士の連結にコストがかからないから 状況が許すならそれも高速、安価で便利^^
画像処理で垂直方向の連続性は重視しないからとdeque<vector<T> >にしたら驚くほど遅くなったな。 垂直方向は参照回数少ないからそんなに遅くならないと思ったのに。
いくらメモリプールしたところで実際に100バイトの転送が発生すれば遅い。ポインタの付け替えだけなら どれだけ巨大でも4バイトの挿入だけ。
馬鹿か垂直方向でもメモリの前後順序性は崩れないだろうが
メモリ確保がボトルネックなっているなら Googleメモリ確保使うと良いよ。 ソースコードの変更無しで最適化出来る。 しかし、メモリ確保でボトルネックになっているのは ほとんど処理してないって事。 もともとのソースがへぼってこと。
>>696 ,, -──- 、._
.-"´ \.
:/ _ノ ヽ、_ ヽ.:
:/ o゚((●)) ((●))゚oヽ:
:| (__人__) |:
:l ) ( l:
:` 、 `ー' /:
:, -‐ (_). /
:l_j_j_j と)丶─‐┬.''´
:ヽ :i |:
:/ :⊂ノ|:
なんだ、本当のことを言われてくやしかったのか? 「定量化できないものは評価できない」
まじめに議論するところでもないんだなこれが・・・
そうでもないよ。それはその時にいる人間のレベル次第。 無能なドカタが、実生活では絶対不可能な上から目線を楽しみに来てる時とかは まじめな議論にはならんが、いつもそうと決まったわけでもない。
listは10万要素くらい一度に確保するとめちゃめちゃ遅いのもデメリットか
mapやlistは使い所が難しいところ。 速度は気にしないならいつでも使える。 dequeもそう。 基本はvectorとstringだな。 これでも使い方次第でパフォーマンスが落ちるが。
vectorは再配置が起きると、以前の2倍確保するらしい。 これがかなりくせ者。 自前で確保したなら50Mで済むところが 自動だと100M確保したりする。
再配置の起こらないvector互換クラスはない物か。 fileをHDDに記録するように分断しつつvectorの機能も使えるやつ
そりゃdequeじゃね?
dequeは再配置はしないの?
>>728 構造的にFATと似てるので、HDDと同じような
索引テーブル上の再配置しかしないのじゃないかと思う。
730 :
729 :2009/12/09(水) 06:31:55
あーごめん。挿入すると再配置発生するそうだ
>>724 mapの使いどころは簡単。
キー検索を多用するときだろ。
>>725 それは実装によるんだろうが、じゃあ
どんなアルゴリズムがいいのか、
というと、難しいだろう。
アロケータみたいに、テンプレート
型引数で、容量拡張方法を設定
できてもいいのにね。
単にラップしてreserveを自前で行うようにすればいいだけ。
vector 要素追加: O(n) 要素削除: O(n) ランダムアクセス: O(1) list 要素追加: O(1) 要素削除: O(1) deque 末端要素追加: O(1) 末端要素削除: O(1) 中間要素追加: O(n) 中間要素削除: O(n) ランダムアクセス: O(1)
ビッグオー表記における定数時間とは 毎回1マイクロ秒でも定数だし 毎回100000000000時間でも定数には違いない。
>>736 > vectorの存在価値ないな
>>735 がいってるようにランダムアクセスO(1)でもvectorとdequeでは実際に要する時間は違う。
dequeはめっちゃ遅いぞ大抵の処理系では
末端からニョキニョキ伸び縮みするような構造のために作られたものだからな 要するにstackとqueue用 でも遅すぎるので誰も使わない
固定長配列でok
dequeのバッファが最近の実装になるほどサイズが小さい傾向にあるのは 何でだろう?
大抵の実装でvectorの要素追加がときどきO(n)になるけど、 これって仕様に明記されてたっけ?
されてる というかO(n)はデタラメで本当は別の定義がなされているからな たまにとんでもなくコストが掛かるぜ
正しくは償却時間
償却時間はεπιστ?μηが勝手に作り出した謎の単語だ
まあ正しくは償却時間計算量あるいは償却計算量あたりかな 意味不明というほどではないが
JISにはなんて書いてあるんだろ。 戻り値も正しくは返却値って言うんだってね。 知らんかった。
>>747 「償却定数〜」じゃないと意味わかんないってば。
JISでは「みなし定数時間」とかだったような 償却でも別にいいと思うけどね 「戻り値」や「フレンド関数」と同じくらい何を指してるか明白だと思う こないだC++相談室で見た「テンプレートクラス」は謎杉だと思った 誰だよ考えたやつ
クラステンプレートで書かれたクラスなんじゃね?<テンプレートクラス
クラステンプレート:template<typename T> class Hoge; テンプレートクラス:Hoge<int> ?
素直に考えればクラステンプレートはテンプレートの一種でテンプレートクラスはクラスの一種であろうと考えるのは自然な考え。
それに沿えば
>>753 のどこに謎があるんだ?。
>>571-754 言葉のうえで
戻り値が returns を指し、フレンドが friend を指すってのは理解できるが
テンプレートクラスが instantiated class を指すってのはちょっと理解できないな
JISにもそんな言葉はない(実は1箇所あるんだけどねw)
もちろん、
>>752-754 のような想像をすることはまったく難しいことではないし、
JISの具現されたクラスの代替が欲しい気持ちも分かる
謎なのは instantiated class からどうやってテンプレートクラスっていう言葉を生み出したのかってこと
たとえば、禿が「instantiated classよりもtemplate classのほうがよくね?」って言ったなら謎はそれで解決
そもそも
>>751-754 はどこでその言葉を覚えたのかが気になる。できれば教えて欲しい
template<...> class ... テンプレートクラスって読みたくなるだろ?
クラステンプレート 関数テンプレート メンバ関数テンプレート
>>755 > そもそも
>>751-754 はどこでその言葉を覚えたのかが気になる。できれば教えて欲しい
なんで
>>751-754 がその言葉を以前にどこかで覚えていたということが確定事項なんだ?
>>752 は推測を書いてるだけだし
>>754 は単語の意味論で素直に推測をした場合には
>>753 が書いた具体例に問題は見つからないと書いてるだけのようだが。
そんなことはたった今知ったばかりの言葉についても書けるだろ。
C++ Templates: The Complete Guide 7.1 にも記述があるね
> クラステンプレート、テンプレートクラス 俺はC++3rdでそう学習したけど。 っていうか今の今まで、他に呼び方が存在するなんて思ったこともなかった。
>>761 を引っ張ってきた人エロイ!
template function とかもあるね
そりゃ日本人も外人も適当に名詞化するわなあ
規格にあってもinstantiated classじゃただの実体化されたクラスの意味でテンプレートとの関係をうかがわせるものは何もないからな。 規格にない俗語でもより本質に近い言葉があればそっちのほうを使いたくなるわな。
うかがわせてるだろ十分に。
そのプログラム中でインスタンスが生成されたクラスのことですか?
循環参照リストをSTLコンテナとして作ろうとしたら beginとendが一緒になってしまって STLコンテナには成れなかったでござる
よくわからんけど *begin == *end かつ begin != end なイテレータにすれば? 余計なフラグを持つことになってオーバーヘッドになりそうだけど
>>769 循環参照リストにするからには
circular<int> c;
// 10個くらいpush_back
std::vector<int> v(c.begin() + 5, c.begin() + 5);
みたいな使い方もしたくて、
begin != end にしても無理だと思う。
そうすると、beginかendであることを示せる特殊なイテレータを生成できればいいわけだな。 例えば、inc/decされていない同士の比較は常にfalseを返すとか。 要素数0のときはちょっと考えないといけないが。
循環参照リストでなく循環リストでないの? おいといて、begin,endをオフセットさせるメンバとか、内容でなく移動距離で比較するイテレータとか用意すれば? circular<int> c; // 10個くらいpush_back c.setiteroffset(5); std::vector<int> v(c.begin(), c.end()); std::vector<int> v((c.begin()+5).resetmove(), c.distanceiter(c.size()));
773 :
デフォルトの名無しさん :2010/01/09(土) 14:38:06 BE:1050556875-2BP(0)
class C { C(char*psz){}; C(int n){}; }; とすると、 C c[]={"hogehoge",0xaf0}; と設定できますが、 std::vetor<C> vc={"hogehoge",0xaf0}; と設定出来ないのは何故でしょうか? 設定する方法などがあればご教授願いたいのですが。
775 :
774 :2010/01/17(日) 18:53:46
間違えた ×>vetor ○>vector
>>774 現行の規格では = {...} によるクラス型の初期化を定義する方法が無いから。
次の規格改訂で可能になる。
777 :
デフォルトの名無しさん :2010/01/25(月) 22:26:42
イテレータの要素を全部足すのってどうしたらいいですか?
template<class Dest, class Iterator> typename void add_range(Dest& dst, Iterator first, Iterator last) { for(; first != last; first++) dst += *first; };
>>777 #include <numeric>
std::accumulate()
トンクス
for( Particles::iterator pi = ps->begin(); pi != ps->end(); ++pi ) { for( Particles::iterator pj = ps->begin(); pj != ps->end(); ++pj) { ・・・ } } このようにイテレータを作っているのですが、このままでは範囲がΣi(0〜N)Σj(0〜N)というふうに計算されるのですが Σi(0〜N-1)Σj(i+1〜N)というふうに計算するにはどうおけばよいのかわからないので質問させていただきます。
for( Particles::iterator pi = ps->begin(); pi != ps->end()-1; ++pi ) { for( Particles::iterator pj = pi; pj != ps->end(); ++pj) { ・・・ } }
>>782 pj = pi + 1 じゃなくていいの?
イテレータの種類はランダムアクセス可能なやつなのかどうなのか ランダムアクセス不可ならstd::advance必須
adavanceなんぞ使わんでも++pj != ps->end();で十分じゃね
二つ前のレスも読めんのか馬鹿が
788 :
781 :2010/02/01(月) 00:47:17
遅れましたが
>>782 のように置いたのですがどうもうまくいかないみたいです。
std::advanceってランダムアクセスイテレータの場合だけ別処理になったっけ?
for( Particles::iterator pi = ps->begin(); pi != ps->end(); ++pi ) { for( Particles::iterator pj = ps->begin(); pj != ps->end(); ++pj) { if(pi >= pj) continue; ・・・ } } で解決しました
これはひどい
>789 > 14882:2003 24.3.4p1 > Since only random access iterators provide + and - operators, the library provides two function templates > advance and distance. These function templates use + and - for random access iterators (and are, > therefore, constant time for them); (後略) ってことでちゃんと別処理だね。
ランダムアクセスイテレータは+と-オペレーターのみを提供するので、ライブラリーは二つの 関数テンプレートに前進と間隔を提供する。 それらの関数テンプレートは+と-をランダムアクセスイテレーターのために使う。 その結果それらの為にそれらの関数テンプレートは定数時間です。
ああ、一箇所間違い発見、さてどこでしょう。
のみ
一箇所どころじゃねーだろ
では2箇所ということで・・・ もう一つはどこでしょうか。
2ちゃんに書いてしまったこと
イテレータの種類による分岐はiterator_categoryの型による特殊化なのかな?
>>799 VC9は
template<class _Iter> inline
typename iterator_traits<_Iter>::iterator_category _Iter_cat(const _Iter&)
{
typename iterator_traits<_Iter>::iterator_category _Cat;
return (_Cat);
}
template<class _InIt, class _Diff> inline
void advance(_InIt& _Where, _Diff _Off)
{
_Advance(_Where, _Off, _Iter_cat(_Where));
}
template<class _FI, class _Diff> inline
void _Advance(_FI& _Where, _Diff _Off, forward_iterator_tag);
以下input,bidirectional,random_access
だった。
d やっぱりiterator_categoryをタグにして特殊化してるんだね。 自作イテレーターの場合に気をつけよう。
vector<int>に対して、すべてのデータが負であるかを判定したい時に 簡単にかけるようなアルゴリズムってある? (forallみたいなの)
全部掛け算して負だったらどう?
MSB の and
-1,1,1の場合にだめじゃん そういうんじゃなくて struct NEG{ bool operator()(int n){return n<0;} }; こういう関数オブジェクトがあれば forall(v.begin(),v.end(),NEG()); こんな感じで呼び出せばtrueがかえる、みたいな感じの
find_if()に負判定の動詞を食わせたら?
あ、それいいですね。thx
MSBだけ取り出してANDするよりも とりあえず全データANDしておいて 最後にMSBだけチェックした方が 全体のコストが減るのでは?
負ゼロはどうすんの
815 :
デフォルトの名無しさん :2010/02/06(土) 08:37:45
vector<int>に対して
>>813 処理系やデータによるとしか。
例えば、できるだけ早く探索を打ち切ったほうが、キャッシュミスが減って速くなるかもしれない。
例えば、処理するデータの正数出現率に片寄りがあるかもしれない。
VS2010beta使ってて、stack<T>にemplaceってメンバがあるんだけどこれって何者?
テンプレ−トタイプ(T)のmoveコンストラクタ呼び出し版のpushかな
なるほど、どうりで検索してもヒットしないわけだ、ありがとう
C++0xの記事がヒットするんじゃねぇの
次のような比較関数を書こうとして必要になったんですが bind3rdってないんですよね struct sorter:binary_function<T,T,bool>{ bool operator()(const T&lhs,const T&rhs)const{ return distance(lhs,x)<distance(rhs,x); //このxを第3のパラメータにしたい } }; //こんな感じで使いたかった sort(v.begin(),v.end(),bind3rd(sorter(),v[0])); こういう場合いい方法ってありますか?
>>821 sort(v.begin(),v.end(),boost::bind(sorter(),_1,_2,v[0]))
別にbindする必要なくね? struct sorter:binary_function<T,T,bool>{ const T &t_; sorter( const T &t ) : t_(t){} bool operator()(const T &lhs, const T &rhs) const{ return distance( lhs, t_ ) < distance( rhs, t_ ); } }; sort( v.begin(), v.end(), sorter(v[0]) );
目からウロボロスでした。助かります
ファンクターの保持、コピー、使用のタイミングはそれぞれ規定がないから ファンクター内で凝った副作用をさせないようにね。
一年くらい前と同じ話題を振るとはなかなかやるな
そういや結構長持ちしてるんだなこのスレ。
valarrayの質問はどこでしたらいいですか?
標準でテンプレートによるライブラリだからここでもいいだろうしC++相談室でもいいだろうし。
std::sprintfおせーぞ なんとかしろや
STLじゃねーよ 速度クリティカルなところでsprintfなんて使うな
律儀だな
ん、じゃー何を使えばいい? そもそも速度が要求される所で、文字列をこねくり回すのが間違い?
printf/sprintfは内部で使用メモリやらCPUリソースやらがものすごい事になってるんで デバッグや速度必要なところでは使うなよ
かといって代わりのコード書くとなると ものすごい事になるし
フォーマットする部分が酷いんだからそこを特殊化すればよろし
コンテナを受け取るtemplate<class T>で、コンテナタイプで特殊化したい場合は T::container_categoryでできますが、イテレータ型を受け取る場合は同じことって不可能でしょうか?
std::iterator_traits<T>::iterator_category
iterator_categoryで分かるのはランダムアクセスとかで、コンテナの種類が正確には分からないのでは?
std::vector<T>::iteratorとかでオーバーロードするんじゃね
一般にイテレータ型からコンテナ型の導出はできない。 例えばイテレータの実装が単にポインタだったらコンテナは?
traits
>コンテナタイプで特殊化したい場合はT::container_categoryで〜 ってのがあんまり意味が呑み込めないというか iterator_categoryみたいにタグディスパッチでオーバーロードするって話なのか? ってかcontainer_categoryってSTLにあったっけ? boostのcontainer_traitsでそんなようなのものを見た記憶があるけど
844 :
デフォルトの名無しさん :2010/03/04(木) 10:42:40
質問です。 std::set<std::string>を使おうとすると、どうしてもエラーになってしまいます。 std::set<std::string> s; s.insert("1"); setとstringは組み合わせられないのでしょうか? set<int>などは普通に使えているのですが…。 環境はVS2008です。
すいません。#include <string>していなかっただけでした… STLのエラーメッセージはわかりづらいよ…(自分が悪い)
コンテナの内容を表示するこんなマクロを書いたんですが tを入力しなくてもよいように出来たりしますか? #define SHOW(v,t,sep) copy((v).begin(),(v).end(),ostream_iterator<t>(cout,sep));cout << endl
template <typename T> void Show(const T &v, const std::string &sep) { std::copy(v.begin(), v.end(), std::ostream_iterator<typename T::value_type>(std::cout, sep.c_str())); std::cout << std::endl; }
マクロ使うにしてもブロックで囲むか セミコロンをカンマに変えないと下のように書いたとき 意図しない動作になるよ if(〜) SHOW(〜);
単純にブロックで囲むとそれはそれで問題なので do { /* */ } while(0) が普通。
双方向イテレータはどうしてランダムアクセス出来ないんですか? 前方と後方に自由に進めるならランダムアクセスできると思います。
計算量が多くてもランダムアクセスできた方が便利なのに あえて出来ないようにして何か得があるんですか?
std::advanceで出来るでしょ 単に[]演算子を提供してないだけで、 それはわざとそういう設計になってる
>>854 特定の利用ケースでそのほうが便利なのであれば、ランダムアクセスできるかのような
インターフェースをかぶせることはプログラマの自由。
一般的には、計算量を無視することは不適切。
ありがとうございます。 ランダムアクセスと双方向イテレーターを分ける 計算量ってどれくらいですか?
>>857 ランダムアクセスが O(1) で双方向がコンテナのサイズ N に対して O(N) 。
O(1) とは言っても償却定数時間が許されていたかもしれない。
1とNの間はどっちにしたらいいですか?
酸素とオゾンだろ常識的に考えて
N/2とかは?
あと計算量がインデックスに依存する場合も教えてください。
宿題っぽいな
どんだけ人に頼ってんだよアホか
>>854 君が その遅いランダムアクセス子を知らずに使ってしまうからだよ
その前にO(N)とかの意味がわかっていないような・・・
>>868 >ランダムアクセス子
イテレータにもキャラ化の波が。w
>>863 O(N/2)=O(N)
これがわからなければでなおせ。
f(N) が O(g(N)) とは N>M ならば f(N) < C g(N) となるような M と C が存在すること?
>>872 なんかよくわかんないんだけど、計算量の話じゃなさそうだから、たぶんちがう。
Taylor展開の剰余項みたいのをイメージしろ。
873は何をいいたいのだろうか
O(N^(1/2))などは1とNの間だろ?
ああ、NとN/2が同じってことがわかんない人につっこんでんじゃなくて 1とNの間の話ね lognとかもそうだな
元の質問の話なら > 1とNの間はどっちにしたらいいですか? 「どっち」かじゃないとダメなんじゃね?
そんなわけないだろ、 ツリー構造みたいなのだとlogじゃね?
なんだか高度そうなお話しているとこ申し訳ないのですが、 「最後の要素を指すiteratorを取得する」方法はありますでしょうか? 現在のところ…。 list<int> m; m.push_back(1); list<int>::iterator it; it = m.end(); --it; // これで、iteratorが最後の要素を指すようになったぞ とやっているのですが…。 push_backは返り値を返しませんし、backは参照を返されるので、末尾のiteratorを得るにはこれしかないのかなと
m.rbegin();
なるほど! ありがとうございます
&m.back()でよくね。 ポインタもイテレータさ!って感じで使ってもSTL的には困らないし
list<int> m; int const *it = &m.back(); while(++it != m.end()); こうですかわかりません
相談室の質も落ちたな・・・ 間違いだらけじゃねーか
>>887 間違いだらけ? >884 のほかに何かあるか?
ツリー構造のコンテナのイテレーターは何イテレーターが適していますか?
>>888 iteratorがポインタで実装されているという保証は一切ない
>>888 は884が間違ってるって指摘だろ
それは884の内容じゃん
俺も「>884のほかに(やりかた)何かあるか?」という意味でとれた
>>892 それはちょっと自身の読解力に不安を持ったほうがいいレベル
>>889 選ぶとすればbidirectional_iteratorかなぁ
たとえばinorderならrootから左右にすすめるコンテナとみなせるわけだし
tree<int,sorter=less<int>,order=inorder<int> > t;
木もSTLにあったら良いのに
list<int>::iterator it = --m.end(); 881 を見て、一行で書くとこうなるのかなと思ったのですが これだと RVO は効かなくなるのでしょうか?
Nに関係なく定数ならランダムイテレーター それ以外は双方向イテレーターでいいですか? コンテナのインデックスがIとしてO( I )とかO( I^2 )は 双方向かランダムどっちですか?
>>896 そんなオーダーはない。
平均するか最悪の場合を考える。
O(N)かそれより大きければ基本bidirectionalじゃね?
日本語でおk
>>889 仕様と実装による。
普通は、イテレータにあわないと思う。
どこかでみたなツリーのイテレータ 幅優先か深さ優先かで二つ定義されてた記憶が
tree.hhを思い出した
std::map の内部とかで 使われてなかったっけ? xtree か何かそんな感じの あれってイテレータ持ってなかったっけ あったなぁ tree.hh GPL だったから使わなかったけど、すごい参考になった
tree.hhってのが何かしらないけど 自分でツリー書いて幅か深さ、必要なのをtemplateでtag受け取って特殊化して組めばいいだけの話ではないの?
tree.hhも知らないなんてダッセ〜
あれ?tree.hhってGPLだったっけ?
不審なファイルはGPLだと思って扱った方がいい 感染ってからじゃ遅い
Boost.PropertyTreeはどうなっているんだろう? あれも構造としては木だけど。
tree.hh使わないとツリーも実装できないなんてダッセー
B木とか赤黒木とか自分で書きたくないです
プログラム素人がプロの書いたコードに勝てるわけ無いだろw おとなしく権威には従えよ
プログラム素人が「初心者」って意味なら勿論勝てるわけないし、 有名どころのライブラリを書いてるプロが優秀なのも言わずもがなだが、 もしそのついでにアマチュア全般とプロ全般を比較したがっているなら、 これについては、コードの品質とは殆ど関係無い。
プログラム素人が「初心者」 でないとしていきなり アマチュア全般 ですか おめでたいですね
5行も使って読解力の無さをアピールされても・・・。 いきなりというなら、いきなりプログラム素人とか言い出す人が問題なんだよ。
また読解力の無い馬鹿が湧いてきた。
>>910 いや実用的な物は書けないかもしれないが
後学のために実験プログラムを書くことは、赤黒木のソースを
読むときに大いに役立つぞ
setの要素をファイルに書き出して、またsetに読み込めるような関数を作ったんだ。 そこでiteratorが指す位置も保存して、また復元できるようにしたい。でもできない。 助けてくださいエロい人。
>>918 なにを試して「できない」と判断したの?
iteratorそのものを保存するんじゃ無理だろ。 何回++したらendと等しくなるかとかを保存しないといけないんじゃねーの 意外と面倒臭いなこれ……
キーとして機能してる値を保存じゃダメなのかい
そもそもsetは、あまりiteratorを介してアクセスするものじゃないよね。 どちらかというと全体で一塊で意味のあるようなデータだし。 問題のiteratorの保存/復元だが、値を保存して読み込むときにfindでいいと思う。
>>918 distance と advance を使ってできることとは違うのかな?
vectorのoperator[]の計算量は定数時間だと思っていたが 正しくは償却定数時間なんだな
要素の参照得るだけなのにそれマジソース総力
C++2003の仕様書の470ページ
実装としてどんなのを想定してるんだろ。
バッファの連続性保証がなかった頃の名残なのかな
vectorの中身が配列とは規定されてはないからね。
>>927 実際にアクセスされるまでメモリの確保が遅延されるシステムとか
単純なコピーオンライト実装だと 非const[]時に償却時間がかかる
>>931 コピーオンライトは、stringだったら
かなりの値打ちだと思うけど、
vectorだったらやりすぎだと感じるな。
std::stackにclear()は無いんですね 空にしたい場合こうやるよりほかにやり方はありますか? while(!s.empty()){s.pop();}
s = std::stack<T>();
メモリが開放されて欲しいか否かによるね
開放されて欲しくない場合は正攻法は
>>933 しかない
reinterpret_cast<std::deque&>(s).clear(); なんて鼻から悪魔な邪道もあるけど
そんな事するくらいなら最初からdeque使った方がいい
>>934 stackってコピー演算子定義されたたのか。これはいいこと知った。
Container c が protected だから継承すれば中のやつもいじり放題。
>>935 それ動くのか?
むしろ、それが機能するstackは使いたくないな。
stackはdequeをメンバに持って そのメンバ関数呼んでるだけだぜ 他のコンテナを使う事もできるが、デフォルトはdeque
なんでSTLとかBoostって命名規則小文字だらけなの? かっこいいけど。
Shiftとか小指疲れるし
SHIFTを押すときに指がつってえらいことになったから
943 :
587 :2010/03/27(土) 20:52:24
“_”もShift使うんじゃない?位置も酷いし。 SpaceShift使うとか工夫すれば良いのにねぇ。
>>939 >他のコンテナを使う事もできるが、デフォルトはdeque
じゃあ実際に何のコンテナを使っているかわからなければ
>reinterpret_cast<std::deque&>(s).clear();
なんて出来ないね
そりゃそうだが、何のコンテナを使うかを指定するのはユーザだから、分からないなんてことはない 型引数にだって残るわけだし
そういう考え方はバグの元 プログラマが管理する物を減らさないとそのうち手に終えなくなるぞ
使ってるコンテナの型はstackがContainerって名前で持ってるから
>>935 解放されて欲しいじゃなくて、解法されて欲しくない場合か、なるほど
そうなると、速度的にはどちらが有利なんだろう
container_typeだった
>>947 大文字の時点で標準じゃ無いだろう。
内部のコンテナを使って欲しいならそれなりのメンバ関数なりtypedefがあるんじゃね?
reinterpret_castは悪い冗談だ。
reinterpret_cast に関しては鼻から悪魔って言ってるじゃないかw そこでマジにならないで
>>951 だからcontainer_typeだってば
規格書にもちゃんと書かれてる歴とした標準のtypedef
直接触りたければ内部コンテナは「c」っていう名前でprotectedになってるから
継承して触ることも出来る
cも規格で決められてるのね ただ仮想デストラクタでないクラスを継承するのもねえ private継承なら安全だけどstackにアップキャストできないし
>>953 そんなDirtyな事はしたくないなあ
そこまでして自分の意見を通したいのか
LIFO以外の操作したい、clear()がないとダメというのなら それはstackがそもそも適していないということでは
>>955 したくないなあ、って誰もやれとは言ってないぞ
自分の意見を通したいのは君自身じゃね?
自分も規格書見て確かめたよ
コンテナにdeque以外が指定されてたらどうすんだ
>>956 stack<hoge> s;
s=stack<hoge>()がスマートかな
961 :
957 :2010/03/28(日) 00:27:37
>>960 記法で代替できるかじゃなくて、選択したデータ構造が
stackである必然がないんじゃないかって話
端的にいえばdeque使えよってだけ
>>961 IDが出ないんだから何とでも言えるわな
>>958 言っておくが、コンテナの種類はテンプレート引数から指定するんだぞ
そしてデフォルト引数がdequeなのは規格で決まっている
stackにpush、pop以外にclearが欲しいという気持ちは分かるが
規格上可能かどうかの話と、推奨されるかどうかの話がごっちゃになってるな
自分で付け足せばいい #include <stack> template <typename T, typename Seq = std::deque<T> > class my_stack : protected std::stack<T, Seq> { private: typedef std::stack<T, Seq> base; public: using base::value_type; using base::reference; using base::const_reference; using base::size_type; using base::container_type; explicit my_stack(const Seq& c = Seq()) : base(c) { } using base::empty; using base::size; using base::top; using base::push; using base::pop; void clear() { base::c.clear(); } };
デストラクタ
デフォルトでいいだろ
そういうこっちゃな Stackアダプタぐらい自作した方が良い
STLのコンテナって継承していいんだっけ
コンテナアダプタはおk?
だって継承ないじゃん 単にガワを被せただけ コンポジションに近い
ちょっと質問の仕方に問題があった デストラクタが仮想でないことに気をつければ コンテナアダプタは継承しても問題ないよね
>>972 そこは public 継承じゃなけりゃ問題にならんだろ。
>>976 public継承しなければコンパイルエラーになるだろ
コンストラクタとデストラクタのあるクラスをprivate継承すると コンパイルできない
んなこたぁない
できねえよ 試してみろよ コンストラクタにアクセスできませんって叱られる
こんな簡単なプログラムでもコンパイルできないよ class A { A() {} ~A() {} }; class B : A { B() {} ~B() {} }; int main() { B b; }
>>982 あったりまえだろう。Bのコンストラクタ、デストラクタがprivateになっとるだろうが。
皆が言ってるのはこうでしょ。
class A {
public:
A() {}
~A() {}
};
class B : private A {
public:
B() {}
~B() {}
};
int main()
{
B b;
}
アホすぎて吹いた
No problem
>>967 でもpublic継承したいところを
涙を飲んでちゃんとprotected継承してるでしょ