関数の作成に関しては、常に 2 つの陣営があるようです。
- 関数内で 1 つの return が見つかるようにしたいもの (通常は最後に)
- データの直線的な流れが好きな人 (通常、複数のリターンがある)
通常、これはより個人的なスタイルですが、パフォーマンスについてお話したいと思います。質問する前に、まず仮説的なシナリオを提案させてください。
要件の状態を考えてみましょう:
Function should first try to calc ReturnVal based off of A. (Typical Case)
If A is unable to be determined then try to find based off of B.
If B is unable to be determined then try to find based off of C.
If all else fails then return C since that is always known.
Function should return enum which states which way the value was found.
したがって、次のようなものがあるとしましょう。
enum HowFound
{
eWithA,
eWithB,
eWithC
};
HowFound CalcReturn(int& nValue) const;
私の質問 速度 (jmp の数など) に関して、ほとんどの場合、コンパイラーがより適切に最適化できると思うスタイルはどれですか?
スタイル 1
HowFound CalcReturn(int& nValue) const
{
HowFound howFound = eWithA;
const int valWithB = CalcWithB();
const int valWithC = CalcWithC();
nValue = CalcWithA( valWithB, valWithC );
if (nValue == -1)
{
nValue = valWithB;
howFound = eWithB;
if (nValue == -1)
{
nValue = valWithC;
howFound = eWithC;
}
}
return howFound;
}
スタイル 1 では、戻り値を格納し、関数を早期に終了することはありません。1 つのリターンがあり、それは最後にあります。
スタイル 2
HowFound CalcReturn(int& nValue) const
{
const int valWithB = CalcWithB();
const int valWithC = CalcWithC();
nValue = CalcWithA( valWithB, valWithC );
if (nValue != -1)
{
return eWithA;
}
if (valWithB != -1)
{
nValue = valWithB;
return eWithB;
}
nValue = valWithC;
return eWithC;
}
スタイル 2 では、データ フローはより「直線的」になります。値を見つけるとすぐに、関数を終了します。これは、関数内により多くの終了ポイントがあることを意味します。
免責事項:明らかに、各スタイルを微調整できますが、私の質問は同じままです. また、はい、両方の関数を記述して逆アセンブリをチェックすることもできますが (これは私が持っています)、「詳細」が追加されると結果が変わります。私の質問は、どちらのスタイルがパフォーマンスが向上する可能性が高いかについてです (どちらかの場合)。
ありがとう!