1 名前:デフォルトの名無しさん mailto:sage [2007/04/29(日) 09:54:14 ] コンパイラ性能、コンパイルオプション、コードの最適化などについて語りましょう。 主に速度面の最適化を中心としますが、サイズなどの最適化もどうぞ。 なお、OS、CPU、コンパイラなどは限定しません 前スレ C、C++の最適化について語るスレ pc11.2ch.net/test/read.cgi/tech/1084676298/
40 名前:デフォルトの名無しさん mailto:sage [2007/05/06(日) 00:22:09 ] ま、ダンゴさんに言わせれば、VCはクズだがな(笑)
41 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/06(日) 00:28:51 ] >>40 はゴキブリかな
42 名前:デフォルトの名無しさん mailto:sage [2007/05/06(日) 03:45:45 ] >>34 ものによるが、キャッシュが効きやすくなるか、ベクタ化しやすくなるか、ループの最適化をしやすくなる。 AoS の方がこれらに有効なこともあるので、ものによるとしか言えん。
43 名前:デフォルトの名無しさん [2007/05/08(火) 00:40:06 ] グローバル変数Aを算出し、算出した関数内でAを参照したいときは、 @直読み A算出時にローカル変数で一度算出しておき、それを参照(レジスタ参照で高速化を狙う)。Aは適当なところでローカル変数を代入 どちらがより良いソースコードになるでしょうか・・・。 @は見やすくてコード量も減りますが、いちいちRAMにアクセスしそうなので実行速度に懸念があります。 Aはローカル変数を用いることにより実行速度の向上を狙いますが、コード量の増加(ローカル変数増えまくり)や オブジェクトサイズに懸念があります。 いまいちどちらにしたらよいかの判断が出来ませぬ・・・。 みなさまはどうされてます?
44 名前:デフォルトの名無しさん mailto:sage [2007/05/08(火) 00:43:33 ] よくわからんが、関数・グローバル変数あたり、 待避と復旧用のコードが増えるだけでそ? あと、レジスタに振られたローカル変数は消えるから。
45 名前:デフォルトの名無しさん mailto:sage [2007/05/08(火) 00:50:12 ] >>44 レスどうもです。 「関数・グローバル変数あたり」が分かりませんでしたが・・。 ローカル変数を用いてレジスタアクセスを狙っても結局スタックに退避したら 変わらないってことでしょうか?
46 名前:デフォルトの名無しさん mailto:sage [2007/05/08(火) 01:15:00 ] 実測するしかないだろ。常識的に考えて。
47 名前:デフォルトの名無しさん mailto:sage [2007/05/08(火) 06:09:18 ] >>43 俺様用語で抽象的なコードの質問されてもなぁ。 自分で最低限のコードを書いて、コンパイラに最適化させてアセンブリ出力見比べてみなよ。 まぁ、>46って結論が待っているけど。
48 名前:デフォルトの名無しさん mailto:sage [2007/05/11(金) 06:47:42 ] 最適化第一法則 最適化するな 最適化第二法則 まだ最適化するな の意味の深さがまだ理解できていないと見えるな。
49 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/12(土) 08:40:11 ] GCCってforループのiをインクリメントからデクリメントに変えるだけで 性能上がったりするよな VC++なんかはループの最適化だけはアグレッシブだから ほとんど気にする必要ないんだが
50 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 12:15:26 ] 終了条件がたまたま 0 だったりするからじゃなくて?
51 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/12(土) 12:29:07 ] 0との比較のほうが命令数が少なくてすむんだよ
52 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:31:43 ] restrictedが使えるコンパイラってアルの?
53 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:33:48 ] あります。
54 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:35:58 ] >>53 bcc32を使っているのですが、うまくいきません
55 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:40:26 ] そんなもんに期待する方が間違っています。
56 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:40:26 ] あとiccもダメでした。
57 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:41:43 ] iccではちゃんと使えます。
58 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 13:42:04 ] そんなもんに期待する方が間違っています。
59 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/12(土) 13:44:27 ] iccは9.1あたりから対応してるはず。VC2005コンパチだし。
60 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 14:29:43 ] そもそも restricted じゃなくて restrict だな。 GCC も余裕で使える。
61 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 14:30:50 ] そんなもんに期待する方が間違っています。
62 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 17:19:55 ] VC++は、2005から__restrictが導入されている。
63 名前:デフォルトの名無しさん mailto:sage [2007/05/12(土) 23:41:50 ] __ かよ。 C++ でも使えるってことなのかな?
64 名前:デフォルトの名無しさん mailto:sage [2007/05/13(日) 00:06:03 ] VCはc99じゃないからね。
65 名前:デフォルトの名無しさん mailto:sage [2007/05/13(日) 01:21:12 ] ダンゴ先生に言わせればVCはクズだしなw
66 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/13(日) 01:45:59 ] >>65 は屑
67 名前:デフォルトの名無しさん mailto:sage [2007/05/13(日) 03:40:23 ] 烏賊自重しろ
68 名前:デフォルトの名無しさん [2007/05/17(木) 16:38:10 ] 長い数式の場合、複数の文に分けて書いた方が最適化しやすいのでしょうか、それとも一気に一つの文に詰め込んでしまった方がよいのでしょうか?
69 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 16:42:45 ] 場合による
70 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 16:43:21 ] っ 実測
71 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 17:04:13 ] そういう最適化は尚早な最適化や、個人の好みでしかない事の典型的な例
72 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 17:29:12 ] オーバーロードしてるような時は コピーコンストラクタが実行されないように 分けた方がいいやね。
73 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 17:39:47 ] >>68 先ずは読み易く書き、適切なコンパイルオプションでコンパイルし、そこが速度上のネックになっていないか測定し、 ネックになっているようならそこで初めて、そこを抜き出して両方のケースを測定してみることだ。 まぁ、コンパイラが適当に最適化してくれるから大差ないと思うよ。
74 名前:デフォルトの名無しさん mailto:sage [2007/05/17(木) 21:24:07 ] ダンゴさんの締めのレスが待ち遠しいな
75 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 01:59:50 ] 団子って良く呼ばれるけど、 書き込んだら書き込んだで叩かれるんだよな
76 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 02:04:33 ] 呼ばれてしゃしゃり出て叩かれることを学習させないと。 赤子と同じ。
77 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 08:26:43 ] 赤子みたいなレスだなw
78 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 11:36:25 ] 赤子はこれから学習するが 団子は学習した結果
79 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 13:50:28 ] スキルの無い奴の粘着人格攻撃を受けられれば、コテも一流だな。 団子の圧勝か・・・。
80 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 20:13:30 ] 団子は好きだけど思い込みが激しいから反芻してから発言して欲しい。 オレモナー
81 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 20:43:54 ] 試しに >>80 を反芻してみた。 込みいからが発言して欲モ激しから反芻してい団しい。 オレ子は好きだけど思ナー
82 名前:デフォルトの名無しさん mailto:sage [2007/05/18(金) 21:04:05 ] 団子が負けたところを見たことがない はっきり言って最強
83 名前:デフォルトの名無しさん mailto:sage [2007/05/19(土) 00:29:20 ] 逃げるが勝ちってか
84 名前:デフォルトの名無しさん mailto:sage [2007/05/19(土) 00:30:36 ] 糞壁と一緒だな
85 名前:・∀・)っ-くコ:彡- mailto:sage [2007/05/19(土) 00:38:34 ] お塩先生に負けますた 矢田亜希子たん取られますた
86 名前:デフォルトの名無しさん mailto:sage [2007/05/24(木) 20:42:26 ] >81 どういうアルゴリズムを適用するとその並びになるのか教えてくれ
87 名前:デフォルトの名無しさん mailto:sage [2007/05/24(木) 20:58:46 ] 反芻アルゴリズム 攪拌ではない
88 名前:デフォルトの名無しさん [2007/06/07(木) 10:55:11 ] vectorは[]でアクセスできますが、これってメモリ上でも連続しているということでしょうか? 配列と比べても、実行速度は変わらないと考えてよいのでしょうか?
89 名前:デフォルトの名無しさん mailto:sage [2007/06/07(木) 11:01:05 ] 最新の仕様では連続してる事が保証されてた気がする。 ただ、それは別に [ ] でアクセスできるからという理由ではない。 こいつは演算子オーバーロードされてるから。 例えば deque なんかも [ ] でアクセスできるけど、 こいつはメモリ上の連続性は保証されてない。
90 名前:デフォルトの名無しさん mailto:sage [2007/06/28(木) 02:32:29 ] >>88 vectorは連続している事が保証されているので、いざとなったら先頭アドレスを取り出して配列としてアクセスすることも出来るよ。 あと、配列の[]やvectorのoperator[]は境界チェックをしないけど、vectorのat()は境界チェックをするよ。知ってたらごめんね。
91 名前:デフォルトの名無しさん mailto:sage [2007/06/28(木) 17:21:44 ] >>88 逆に言えば、添え字演算子[]で読み書きできるからといって、 メモリ上で要素が連続している保障があるとは限らない。 dequeとかmapとか。
92 名前:デフォルトの名無しさん mailto:sage [2007/07/15(日) 14:57:49 ] >88の人気に嫉妬
93 名前:デフォルトの名無しさん [2007/08/03(金) 20:43:46 ] Intel compilerのx64版を使っているのですが、 レジスタにある筈の値を何度もメモリに読みにいったり、 もう使わないローカル変数をメモリに書き込んだりしています。 ループの奥底なので許容できません。VTune で見てもボトルネックになって いるようです。 深い理由があってのことででしょうか? それとも、x64版の熟成が未完なのでしょうか? 32bit版との賢さの違いについてどんな印象をお持ちですか?
94 名前:デフォルトの名無しさん mailto:sage [2007/08/03(金) 21:19:37 ] 64bit版は知らんけど、32bit版もインテルが自分で言うほど 飛びぬけた性能でもないような…。 体験版で試して、俺のプログラムはVCに全敗したから、買う のやめた。Linuxだと他に選択肢が無いのかも知れんけどね。
95 名前:デフォルトの名無しさん mailto:sage [2007/08/03(金) 21:42:37 ] ウチの場合はICCのが何割か速かったよ。画像処理で。 GCCとVCと比較してもっとも早かった。 64bit版はさすがに知らないけど。 マルチコアならレジスタにある値だけだとあんまり信用できないからかね?
96 名前:デフォルトの名無しさん mailto:sage [2007/08/03(金) 22:02:01 ] ポインタをdereferenceした値なんじゃないの
97 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 01:58:07 ] >>93 const付けられるところには全て付けてるよな? 関数ローカルのauto変数とか、クラスのメンバ関数(not変数)とかにも。 それでエイリアス問題とかが片付くから、割と変わるぞ。
98 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 02:10:28 ] エイリアス問題はconstじゃ解決しないぞ restrictキーワードが要る
99 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 03:29:23 ] ん? メンバ関数がconstなら、その関数内から見たらクラスのメンバ変数は皆const扱いだろ? となると、複数のポインタor参照でメンバ変数を参照したり、キャッシュを持ったりしても実害が無いだろ? 変更がありえないんだから。 つまりエイリアスが発生しても、それが問題にならないケースがあるわけだ。 (グローバル関数経由の変更というものもあるので、確実じゃないけどな) もちろん、クラスのメンバ以外を操作するならrestrictが必要だな。 それはおっしゃる通り。
100 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 12:12:12 ] constは、「プログラマが」変数を書き換えないという表明であって、 値が変化しないことの保証にはならない。 ポインタor参照経由の値は、 常にaliasの可能性があるとコンパイラはみなさなければならない。 というか、最適化のためのconstnessの判断はコンパイラがやることなので、 最適化フェーズではregisterキーワードよろしく無視されると考えていい。 と似たことを以前constでメシがナンタラというスレで書いた気がする。
101 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 13:00:20 ] こういうことかな・・・? class A{ public: int x; void foo(int*) const; }; main(){ A *a = new A(); a->foo(&a->x); } void A::foo(int* p) const { int x1 = x; *p += 1; int x2 = x; // x 読み直し }
102 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 15:53:02 ] うーん、そういうケースも多いだろうけど constがオプティマイザに無視されるということはないと思うぞ。 以前関わったプロジェクトで、constがろくについていなかったので 片端から付けた事があるんだよ。 結果リリースビルドのバイナリが大幅に変わってしまった。 速度的にはそれほどの向上は無かったのが残念だけど(ホットスポットは変わらなかった) 全体的にconstメンバ関数のインライン化が行われていた。 約1%ほどバイナリが肥大化したのはご愛嬌^^;
103 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 16:08:05 ] そりゃまたアホなコンパイラだな・・・ それにその例だと、速度かわらず、バイナリが増えてるんなら無意味じゃないか。
104 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 16:12:56 ] ホットスポットが変わらないから速度の有意差が出なかったのだろ。
105 名前:デフォルトの名無しさん mailto:sage [2007/08/04(土) 19:43:09 ] >>102 そこまで言うならメンバ関数への const の有無で出力コードの変わるソースを 出してみて欲しい。
106 名前:デフォルトの名無しさん mailto:sage [2007/08/05(日) 01:23:48 ] ちょっとやってみたが、短いサンプルだとconstの有無に関わらずインライン展開されて 結局同じになってしまうな…… まあこの場合「const の有無で出力コードの変わるソース」が存在することを 証明できればいいのだから、最適化オプションの調整を含めて もうちょっと詰めてみる。 こっちもデスマ中なので何日かかるかもしれないが、期待しないで待ってろ。
107 名前:デフォルトの名無しさん mailto:sage [2007/08/05(日) 01:29:31 ] 必要なのは「出力コードが変わる」じゃなくて「速度向上に貢献する」だぜ つか、なにもデスマ中にやらんでも(´・∀・`) 元気なときにやろうぜ
108 名前:デフォルトの名無しさん mailto:sage [2007/08/05(日) 02:29:18 ] いや、>>105 がそう言っているんでな。 とりあえず「constで変わりうる」ということを出しておこうかなと。 C/C++では完全な参照透過性を保証する構文が無いから、 コンパイラにとって論理レベルでの最適化は難しいだろうが、 不可能では無い事を明示したい。 まあ今日は寝る。おやすみ。
109 名前:デフォルトの名無しさん mailto:sage [2007/08/05(日) 02:56:49 ] >>108 そこまでわかっていて不可能ではないと思う根拠はなんだろう? 楽しみにしてるよ。
110 名前:デフォルトの名無しさん mailto:sage [2007/08/06(月) 22:23:24 ] 今年プログラム初めてまだまだわからないことだらけで助けてほしいことがある。 複数のファイルより条件に合う行を抜き出して一つのファイルに出力するプログラムを作ったんですが 処理に結構時間がかかってしまいます。何とか速度向上させたいのですが何か良い方法はないでしょうか? 本当は自分でいろいろ試行錯誤してやりたいのですが分け合って時間が取れなくて書き込みました。
111 名前:デフォルトの名無しさん mailto:sage [2007/08/06(月) 22:26:47 ] グレップツール使いな
112 名前:デフォルトの名無しさん [2007/08/06(月) 22:35:17 ] >>110 秀丸つかっとけ
113 名前:デフォルトの名無しさん [2007/08/06(月) 22:36:36 ] >> 93 です。 色々アドバイス頂きながら、返信せず申し訳ありません。 const はきちんと付ける主義です。 わざわざ、{} を追加して、スコープを絞っても、ローカル変数の 無駄な書き込みを止めさせることはできませんでした。 何となく、ICC x64のコンパイル結果って回りくどい気がするのです。 命令のレイテンシとかキャッシュ効率とか考慮された結果かな?
114 名前:デフォルトの名無しさん mailto:sage [2007/08/06(月) 22:40:25 ] restrictについては言及ナシですか。
115 名前:デフォルトの名無しさん mailto:sage [2007/08/06(月) 23:06:13 ] つーか、具体的なコードも出さずにあーだこーだ言われても 「あーそうですか」としか言いようがないなぁ。
116 名前:デフォルトの名無しさん [2007/08/08(水) 23:24:43 ] >>114 何故か書き込み不能になった返信がさらに遅れました。 restrictを使っても、コンパイル結果が同じでした。 仕事絡みなのでコードを出せません。ご了承下さい。 ごく一部を出しても、実害はないと思いますがバレると 厄介なことになりますもので...
117 名前:デフォルトの名無しさん mailto:sage [2007/08/08(水) 23:26:13 ] 別にその仕事とは全く関係ないコードを書けばいいのに。
118 名前:デフォルトの名無しさん mailto:sage [2007/08/09(木) 02:19:54 ] ○○○は糞、だけど証拠は出せません いい流れだ
119 名前:デフォルトの名無しさん mailto:sage [2007/08/09(木) 03:19:58 ] constによる最適化を主張する俺が戻ってきましたよ とりあえずサンプルを作るのは諦めました。そこで 既存のプロジェクトからメンバ関数のconstを外す ⇒ エラーが出たところだけconstに戻す という手順で相違点を調べました。(バージョン管理ツールは便利だねえ) >>102 の環境はVC7.1でしたがライセンスの関係で問題があるので 今回の環境は別のプロジェクトのCodeWarriorです。 で、リリースビルドの結果は以下の通り。 全関数(メンバ関数でないものやライブラリも含む) 12256個 constメンバ関数 253個 検証時にconstを削除出来なかったメンバ関数 24個 const削除前のコードサイズ 2899400 bytes const削除後のコードサイズ 2899084 bytes constを付けた方がコードサイズが増える傾向がありますが、CodeWarriorの場合は インラインされやすくなるという傾向はありませんでした。 また、極端にパフォーマンスが変化するということはありませんでした。 (づづく)
120 名前:デフォルトの名無しさん mailto:sage [2007/08/09(木) 03:40:23 ] 逆アセンブリで見られる具体的な差異としては const有りだと分岐命令の後に来ている命令が const無しだと分岐命令の前に来ている という現象が所々に見られました。 いつ評価しても同じなら分岐の後で評価したほうが得、ということなんでしょうか。 (遅延評価に似てる?) サンプルを上げようかと思ったけど、きわめて眠いのでまた今度。 明日か明後日までに適当なアップローダの紹介を希望。 ではおやすみなさい。
121 名前:デフォルトの名無しさん mailto:sage [2007/08/09(木) 07:15:32 ] 分岐命令をまたいで命令が移動するってのは、動作が変わってるような気がする。 よくわからんからサンプルが欲しいな。ろだ↓ kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm
122 名前:デフォルトの名無しさん mailto:sage [2007/08/09(木) 10:42:03 ] ほい、上げておいた。 ttp://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.cgi?mode=thr&no=4841 全部上げるわけにもいかんので加工してある。 詳細は添付のreadme.txtを読んでくれ。 じゃ俺は戦場に戻る。
123 名前:デフォルトの名無しさん mailto:sage [2007/08/10(金) 09:31:04 ] >>122 リストファイル中のソースとの対応がずれてたり、命令数の違いでアドレス部が ずれてたりしてるけど、本当に命令レベルの違いだけを抽出すると、2箇所だけになった。 -- const無し: lw v1,-21056(v0) addiu a0,v1,436 lw v1,436(v1) const付き: lw a0,-20672(v0) lw v1,436(a0) -- const無し: lw v0,-21056(v0) addiu v1,v0,436 lw v0,436(v0) const付き: lw v1,-20672(v0) lw v0,436(v1) --
124 名前:123 mailto:sage [2007/08/10(金) 09:54:07 ] 2箇所いずれも app->CheckMenu() のところね。逆読みすると、 app 内のポインタが指す配列か構造体から1つ値を読み出してるって感じ なんだけど、やっぱり CheckMenu() のソースが欲しいな。ダメ? const無しのほうにある addiu の結果は使われて無いように見える。 あれ? const 付けたほうがコード増えるって言ってたけど、ここでは 1命令減ってるね。
125 名前:123 mailto:sage [2007/08/10(金) 10:03:26 ] const の有無で最適化に影響が出てるんじゃなくて、オーバーロードに影響が 出て処理が変わってるだけじゃないだろうか? たとえば std::bitset::operator [] (size_t) なんかだと、 const 版は単に bool が 返るけど、非 const 版は代入もできるプロキシオブジェクトが返るのでかなり 違った処理になるはず。
126 名前:123 mailto:sage [2007/08/10(金) 10:31:24 ] あ、 addiu の結果はその後の sw で使われるみたい。 app のメンバオブジェクトについて const 版が int を返して、 非 const 版が int& を返すようなオーバーロードが使われてる予感。 んで int& だと続く書き込みに使いまわせるからレジスタに置かれた、と。
127 名前:デフォルトの名無しさん mailto:sage [2007/08/10(金) 11:09:19 ] やっぱり、単純にはなんとも言えないという結論か。
128 名前:デフォルトの名無しさん mailto:sage [2007/08/10(金) 21:42:46 ] いや、大方の予想通りメンバ関数の const は最適化の助けにはならないって結論だろう。
129 名前:デフォルトの名無しさん mailto:sage [2007/08/12(日) 22:50:05 ] お待たせしました。一時帰宅しました。 辛辣なツッコミを期待していたんだけど、ちょっと物足りないかしら。 まあ、相手してくれてありがとう。 以下質問に対するごお返答。 >>122 CheckMenu()は以下のようなコードになっている。オーバーロードはされていない。 bool CApplication::CheckMenu(int n) { return (m_MenuStatus == n); } ちなみにappはCApplication型のグローバル変数。constではない。 >>128 出力バイナリは違っているのに、そう言いきれるのはなぜ?
130 名前:デフォルトの名無しさん mailto:sage [2007/08/12(日) 22:51:52 ] 小林洋平
131 名前:デフォルトの名無しさん mailto:sage [2007/08/12(日) 23:42:01 ] >>129 関数の中身を晒してくれてありがとう。そういうことなら、素の int 型メンバ変数の 読み取りについてコンパイラ内部で >>126 の言うオーバーロードと似たような扱いが されているんだろう。 今回の例では const が無い場合に int& をキャッシュするために命令数が一つ 増えたとすると、前後の処理内容によってはその int& のキャッシュによって効率が 上がることも考えられる。いつでも const を付けたほうが効率が良いとは言えない。 今回の例で、コンパイラが const 無しの場合に const 付きの場合と同じコードを 吐いても何ら規格に違反しない。最適化の詰めが甘かっただけとも言える。
132 名前:デフォルトの名無しさん mailto:sage [2007/08/13(月) 10:42:15 ] constは保守のための手助けみたいなもんだろ mutableしてない変数に代入しようとしてたらエラー吐くだけの
133 名前:デフォルトの名無しさん mailto:sage [2007/08/13(月) 14:57:53 ] gcc の _attribute((const)) みたいなもんがあればいいのかも。 ・関数の戻り値が引数とインスタンスの内容にのみ依存する。 つまり、 class Test { public: int foo() __attribute__((const)); void bar() const; }; Test T; int a = T.foo(); T.bar(); int b = T.foo(); // int b = a; に最適化できる。
134 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 02:07:27 ] >>132 変数定義時の const はそうでもないよ。 const 付きで宣言された変数は ポインタや参照を関数に渡した後でも、値が元のままであることを期待して 最適化してもいい。 これに対してポインタ・参照の指す先の型や、メンバ関数に付ける const は ほとんどコード生成に影響しないという話。
135 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 02:10:47 ] >>133 それはダメでしょ。 T の宣言に const が付いてないので T.bar() の中で const_cast して 値を変更しても合法なはず。
136 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 02:59:32 ] intメンバ変数一個のstructで試してみたが、 >ポインタや参照を関数に渡した後 では読み直しをやってるなあ。 環境はVC8とgcc3.4.4(cygwin)
137 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 03:34:58 ] >>136 どんなソースで試したの? 以下のソースだと s に対する const によって読み直しが消えて return 10 に最適化される。 const 外すと当然メモリ上の s.x が読み出される。 struct S { int x; }; void f(struct S const* p); int g(void) { struct S const s = { 10 }; f(&s); return s.x; }
138 名前:137 mailto:sage [2007/08/14(火) 03:35:31 ] あ、確認した環境は Cygwin gcc 3.4.4 の -O3 ね。
139 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 09:55:00 ] 似せるとこういう感じ。gccは-O3、vc8は/Oxです。 struct S { S(int x_):x(x_){} int x; }; void f(struct S const * p); int g(void) { struct S const s(10); f(&s); return s.x; } つーか分からないのは仕方ないか。ということで struct S { S(int x_):x(x_){} int x; int getX() const { return x; } }; void f(struct S const * p); int h(int); int g(void) { struct S const s(10); h(s.getX()); f(&s); return s.getX(); } vc8もgcc3.4.4も、分かってるんだか分かってないんだか分からないコードを吐く。 さらに、このコードの int x を const int x にすると、gccは読み直しをしなくなる。 これはsのconst修飾に依存しない。(あれれ?)
140 名前:デフォルトの名無しさん mailto:sage [2007/08/14(火) 10:20:39 ] >>139 ほんとだ。これは期待はずれだなぁ。 コンストラクタ内での代入を許すために const として定義されたという情報が 途切れてしまっている、って感じ? メンバのほうに const を付ければ代入を許すタイミングは無いから、 >>137 と 同様に最適化できる、と。