2011-10-06 12 views
18

は、次のC++のコードを考えます。 私はgccによって生成されたアセンブリ(-Sを使用)を見て、コードジェネのサイズが以前の数百倍も大きかったことに気付きました。奇妙なGCCの挙動

コンストラクタの定義を省略すると、生成されたアセンブリは完全に異なります。

.globl cube 
    .data 
    .align 32 
    .type cube, @object 
    .size cube, 120 
cube: 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .zero 24 
    .text 

明らかに、コンパイラによって生成されるコードには大きな違いがあります。 なぜですか? また、なぜgccはある状況のすべての要素をゼロにし、もう一方の要素をゼロにしませんか?

編集:私は、次のコンパイラフラグを使用しています-std=c++0x G ++ 4.5.2と。

+0

これは野生の推測ですが、これを試してみてください:vertex_type():x()、y()、z(){} – Pubby

+4

@ AlfP.Steinbachこれは正確です私のファイルにあるコード。他には何もありません。あなたのどちらかがコードをチェックしましたか?それは{}を持っています。それはインラインです... – dcousens

+3

@Alf問題のコンストラクタはコメントアウトされています。 – zwol

答えて

14

これは長年のmissing optimization in GCCです。 の場合は、どちらの場合も同じコードを生成することができますが、できません。

コンストラクタがなければ、vertex_typeはPOD構造です.GCCはコンパイル時に静的/グローバルインスタンスを初期化できます。コンストラクタでは、プログラムの起動時にグローバルを初期化するコードを生成することができます。

+1

洞察とリンクをありがとうだけでなく、それはなぜそれが1つのケースではなく、他の残りの要素をゼロにするのですか? – dcousens

+0

この回答は正しくありません。コンストラクタ付きのコードはコンパイルすべきではありません。私の答えを見てください。 – Nawaz

+0

@ダニエルそれは(無関係の)バグかもしれません。私のg ++​​ 4.6.1のコピーは、両方のケースで残りの要素をゼロにします(また、ゼロを埋めるために9976の 'movl'命令を生成しません - 暗黙的に' .bss'を使用します)。私は手にgcc 4.5を持っていません。 – zwol

0

カスタムコンストラクタを使用している場合、コンパイラは作成するすべてのベクトルに対してそのコンストラクタを呼び出す必要があります。自分で作成しない場合は、デフォルトで生成されたコンストラクタが使用されます。しかし、タイプが複雑でないので、それを呼び出す必要はありません。配列はバイナリの定数テーブルとして格納されます。

デフォルトのコンストラクタをインライン展開して空にしてください。もちろん、それは有効になっていても有効です。

+1

私が知る限り、デフォルトのコンストラクタをインライン化することはできません。彼がコンストラクターを投稿したコードは暗黙的にインラインです。 – Pubby

+0

MSVCで__forceinlineなどのコンパイラ拡張を使用することは可能です – crazyjul