2012-01-05 5 views
1

あなたはこのような方法がある場合:変数に複数のクラス呼び出しを格納する方が速いのですか?

float method(myClass foo) 
{ 
    return foo.PrivateVar() + foo.PrivateVar(); 
} 

が、代わりに、これを行うために/常に速いほうがよい?:

float method(myClass foo) 
{ 
    float temp = foo.PrivateVar(); 
    return temp + temp; 
} 

を、私はあなたがfoo.PrivateVar()のようなコールを置くことになっていない知っていますたとえば、forループでは、実際に値を1回だけ使用する必要がある場合、何度も評価するためです(場合によっては

for (int i = 0; i < foo.PrivateInt(); i++) 
{ 
    //iterate through stuff with 'i' 
} 

これより最初の例のようなコードを2番目の例に変更することを前提にしていますが、コンパイラよりも賢くならないように人々に言われました!そしてそれは通話を非常によくインラインにすることができます。

私は何もプロファイルしたくありません。これについては、いくつかの簡単なルールが必要です。私は仕事のアプリケーションのデモを書いています。誰かがコードを見てルーキーミスをすることを望んでいません。

+0

この関数には副作用がないと想定できますか?さもなければ、これは無意味な比較です。 –

+2

どちらかの方法で不平を言う人がいるでしょう。魔法の弾丸はありません。例えば* I *は 'for'ループ最適化を*習慣*にしないことをお勧めします。なぜなら、' PrivateInt() 'によって返された値がループのコース。 IMOの "正しい"ことは、正確で読みやすいコードを書く方法を学び、いつどのように最適化するかを個別に学ぶことです。 – Hurkyl

答えて

4

これは完全にPrivateVar()の処理内容と定義されている場所によって異なります。コンパイラがPrivateVar()のコードにアクセスでき、その関数を呼び出すことによって副作用がないことを保証することができます。あなたの2番目のコード例でやったことがあります。

forループとまったく同じです。だから、一度しか評価されていないことを確かめたいのであれば、それは非常に高価な関数なので(明示的に副作用が発生してもそれが厄介でないことを保証することも意味する)

PrivateVar()がゲッターに過ぎない場合は、コンパイラがCSEを実行しなくても、パフォーマンスの違いはすべてのケースの99.9999%で問題にはなりません。

編集:CSEはCommon Subexpression eliminiationの略であり、正確にはそれを表しています;)wikiページには単純な乗算の例が示されていますが、関数呼び出しのような大規模なコード構造に対してもこれを行うことができます。

a = b++ * c + g; 
d = b++ * c * d; 

し、それを変更する:

tmp = b++ * c; 
a = tmp + g; 
d = tmp * d; 

我々は一度だけのコードを評価するにはつまり、このコードのためにCSEをやって、セマンティクスを変更しないことを保証する必要があるすべての場合において

明らかに違法になるでしょう(関数呼び出しについては、明らかにもう少し複雑ですが、同じ原則です)。

+0

実際、わずか97%です。 –

+3

@Cicada、統計の87%がちょうど構成されていることをご存知でしたか? –

+0

基本的には単純なゲッターでないかぎり、2番目のものをやりますか? forループにゲッターを置くこともOKだと言っていますか?誰もそれのために私を裁かないだろうか? 1つのスタックオーバーフローが、コードの特定の側面を「いいえ」と呼んでいるためです。 – SirYakalot

関連する問題