トップ «前の日記(2006-06-26) 最新 次の日記(2006-06-28)» 編集

豊田正史のSLとは関係ございません


2006-06-27

_ [開発] C++のstd::endl

coutにendlを出力すると死ぬほど遅いのは有名な話なのだろうか?

cout << "hoge" << endl;

cout << "hoge\n";

をそれぞれ1000万回繰り返すと、6.5secと1.7secで、'\n'で改行するのより、3.8倍ほど遅くなる(Itanium2 1.6GHz, RedHat Enterprise Linux)。調べて見たら、endlってflushも一緒にするのね。どおりで。ちなみにprintfだと、1.1sec。やっぱりiostreamは使わないに限る?

本日のツッコミ(全8件) [ツッコミを入れる]
_ さね (2006-06-28 03:44)

そういえば、かつて 吉田弘一郎が「"\n"とendlは挙動が違う」みたいなことを書いていた様な気がしましたが、これって何らかの条件の下で別の挙動を示すのでしたっけ?話題だけふっておいて答えが用意できて織らず申し訳ございません...

_ とよだ (2006-06-28 04:03)

なにせC++使っているくせにcoutとかほとんど使わないもので良くわからないんですが、環境によって挙動が変わるということはないみたいです。フラッシュのあるなしだけのようですね。

_ さね (2006-06-28 14:32)

なるほど。では cout と cerr の両方を同時に使っていたりすると、flush順により別の出力が得られたりするのかもしれませんね。<br><br>> やっぱりiostreamは使わないに限る?<br>やはり、そうなんですかね。<br>学部生の頃は (新しいもの好き的思想で) 好きこのんで cout を使っていたような記憶がありますが、私もいつしかcoutを使わなくなっていきました。大きな原因の1個にDOS時代は console プログラムをしていたが、開発環境がVCに移ってからそもそもconsole を使わなくなったというのもあります。しかし、最大の原因は単にprintfの方が便利だっただけの様な気もします。<br><br>ちなみに、紹介の書籍は これ↓だったかもしません。<br>http://www.amazon.co.jp/exec/obidos/ASIN/4774105570/249-2442429-8337142<br>レビューに<br>> 読者を馬鹿にしたような言い回しと誤字脱字の多さに苛立ちを覚えた. <br>とありますが、その通りかと思います(笑) もう10年近く前の本ですね...

_ と@女王さまの下僕 (2006-06-29 01:49)

いや、まあ、私も今ちょっとだけ確認してしまいましたが、ナノで、偉そうには言えませんが、g++のヘッダのendlの所にはその旨書いてリンクまで張ってあります。勉強になりますた。これって、C++ FAQには書いてあったかしら?<br><br>まあ、operator<<を多重定義しなくてよいならprintf()でも、というのも判らんではないですね。自分で定義しなければ行けない時点で(Perlの)Data::Dumper ... 最近覚えた、でなんかperlでreferenceがちょっとできるようになった...には大分負けている気もしますが。

_ とよだ (2006-06-29 03:09)

あーほんとだ。書いてありますね。リンク先はlibstdc++のFAQなんですね。C++の教科書なんかも注意深く読めば書いてあるのですが、まあ見落としやすいですね。flushが別にあることも心理的トラップになってますし。実は、printfでもややこしいフォーマットをさせるとcoutより遅くなることもあるらしく、かなりややこしいです。

_ と@女王さまの下僕 (2006-06-30 01:38)

「まあ見落としやすい」のはその通りなんですが、通常の能力に加えてこういう地雷原をどれだけ知っているかもプロのC++プログラマとしては重要です、と、アマチュアの私がいってもあれですが。アマチュアなので、家には仕様書がないので覚えていたら調べてみます。多分わすれますが。

_ と@女王さまの下僕 (2006-07-07 01:31)

ふとそんな話題がオフィスでもでたので調べてしまった。JISの仕様では以下の通り。<br><br>27.6.2.7 basic ostream の標準操作子<br>namespace std {<br>template <class charT, class traits><br>basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);<br>}<br>1 効果 os.put(os.widen(’?n’)) を呼び出した後,os.flush() を呼び出す。<br>2 返却値 os。(300)<br><br>注(300) cout << endl を実行することによる効果は,改行文字をcout によって制御される出力列に挿入し,その後,それと関連しているであろう外部ファイルと同期を取ることにある。

_ とよだ (2006-07-07 04:13)

やや、わざわざどうもありがとうございます。<br>os.widen(’?n’)のあたりが微妙に気になりますね。


README日記の書き方