拡張 。
私が次のようなことをしたとき、私はクールだと思いました:
bool hasParent() { return this-> parentNode; }
(bool)キャストを使用しても、警告は消えません。
親ノードがない場合、this-> parentNodeはNULLです。
しかし、私は得ています:
warning C4800: 'Node *':値を強制的にブール値 'true'または 'false'(パフォーマンス警告)
どうしたの?なぜそれがパフォーマンス警告ですか?私は次のようなものを書かないほうが効率的だと思いました:
bool hasParent() { if(this-> parentNode) return true; else falseを返す; }
しかし、2番目のバージョンは警告を生成せず、コンパイラーははるかに満足しているようです。どちらが速いですか?
これについては、Microsoft Connectに関する議論があります( C++でブールに変換すると、パフォーマンスにどのような影響がありますか? )。 Microsoftに与えられた例は次のとおりです。
$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp
1 bool f1 (int i)
2 {
3 return i & 2;
4 }
5
6 bool f2 (int i)
7 {
8 const bool b = i & 2;
9 return b;
10 }
11
12 bool f3 (int i)
13 {
14 const bool b = 0 != (i & 2);
15 return b;
16 }
t.cpp
t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
また、Microsoftの(警告を担当した開発者からの)対応は次のとおりです。
この警告は驚くほど役に立ち、昨日私のコードにバグが見つかりました。マーティンは「パフォーマンス警告」を文脈から外していると思います。
生成されたコードではなく、プログラマが値をintからboolに変更する意図を通知したかどうかです。これにはペナルティがあり、ユーザーは一貫して「bool」ではなく「int」を使用するか(またはその逆の可能性が高い)、「boolifying」コード生成を回避します。以下の3番目のケースでは、int-> bool遷移を受け入れる意思を明確に示しているため、警告は抑制されます。
これは古い警告であり、その目的を長引かせた可能性がありますが、ここで設計されたとおりに動作しています
したがって、基本的にMS開発者は、int
をbool
に「キャスト」したい場合は、「return this->parentNode != 0
"暗黙的または明示的なキャストの代わりに。
個人的には、警告によって明らかになるバグの種類について詳しく知りたいと思います。この警告はあまり価値がないと思います。
bool
にキャストしても警告が消えないという事実 仕様による :
式をbool型にキャストしても警告は無効になりませんが、これは仕様によるものです。
警告C4800のMSDNの説明が推奨するアプローチをお勧めします。
return this->parentNode != NULL;
これにより、true
がnullポインターでない場合はparentNode
を返し、false
がnullポインターの場合はparentNode
を返すことがわかります。
コンパイラーは、ポインターをブール値に変換するための追加コードを生成する必要があります。これは基本的にゼロとの比較であり、ゼロでない場合は結果を1に設定します。
00000000004005e0 <_Z4testPv>:
bool test(void* adr) {
4005e0: 48 85 ff test %rdi,%rdi
4005e3: 0f 95 c0 setne %al
return adr;
}
4005f8: c3 retq
これはソースから直接見えないので、コンパイラーはこれをユーザーに警告する必要があると考えます。
なぜそれがパフォーマンス警告ですか?
コンパイラはこれを回しています:
bool hasParent()
{
return this->parentNode;
}
に:
bool hasParent()
{
return this->parentNode != 0;
}
これには、コードを見ると予想よりも1クロックサイクル長くかかります。それはわずかなパフォーマンスの違いです。
!= 0
とにかく明示的に。これにより、コードがより明確になり、警告が抑制されます。
次のように書くほうが効率的です。
bool hasParent()
{
return this->parentNode != NULL;
}
これはコンパイラに依存していると確信しています
現実的には、同じように最適化すると思います。これを試すこともできます。
return this->parentNode != 0;