web-dev-qa-db-ja.com

boolへのキャストポインターにパフォーマンス警告があるのはなぜですか?

拡張

私が次のようなことをしたとき、私はクールだと思いました:

 bool hasParent()
 {
 return this-> parentNode; 
} 

(bool)キャストを使用しても、警告は消えません。

親ノードがない場合、this-> parentNodeはNULLです。

しかし、私は得ています:

 warning C4800: 'Node *':値を強制的にブール値 'true'または 'false'(パフォーマンス警告)

どうしたの?なぜそれがパフォーマンス警告ですか?私は次のようなものを書かないほうが効率的だと思いました:

 
 bool hasParent()
 {
 if(this-> parentNode)
 return true; 
 else 
 falseを返す; 
} 

しかし、2番目のバージョンは警告を生成せず、コンパイラーははるかに満足しているようです。どちらが速いですか?

53
bobobobo

これについては、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開発者は、intboolに「キャスト」したい場合は、「return this->parentNode != 0 "暗黙的または明示的なキャストの代わりに。

個人的には、警告によって明らかになるバグの種類について詳しく知りたいと思います。この警告はあまり価値がないと思います。

46
Michael Burr

boolにキャストしても警告が消えないという事実 仕様による

式をbool型にキャストしても警告は無効になりませんが、これは仕様によるものです。

警告C4800のMSDNの説明が推奨するアプローチをお勧めします。

return this->parentNode != NULL;

これにより、trueがnullポインターでない場合はparentNodeを返し、falseがnullポインターの場合はparentNodeを返すことがわかります。

28
James McNellis

コンパイラーは、ポインターをブール値に変換するための追加コードを生成する必要があります。これは基本的にゼロとの比較であり、ゼロでない場合は結果を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

これはソースから直接見えないので、コンパイラーはこれをユーザーに警告する必要があると考えます。

8
Gunther Piez

なぜそれがパフォーマンス警告ですか?

コンパイラはこれを回しています:

bool hasParent()
{
  return this->parentNode;
}

に:

bool hasParent()
{
  return this->parentNode != 0;
}

これには、コードを見ると予想よりも1クロックサイクル長くかかります。それはわずかなパフォーマンスの違いです。

!= 0とにかく明示的に。これにより、コードがより明確になり、警告が抑制されます。

7
user9876

次のように書くほうが効率的です。

bool hasParent()
{
    return  this->parentNode != NULL;
}
2
Martin York

これはコンパイラに依存していると確信しています

1
user224003

現実的には、同じように最適化すると思います。これを試すこともできます。

return this->parentNode != 0;
0
UberJumper