web-dev-qa-db-ja.com

比較をNULLまたはnullptrにキャストする必要がありますか?

次のようなC++関数があるとします。

bool Foo(Bar* b)
{
    if(b == nullptr) {
        return false; 
    }
    // Do stuff
    return true;
}

さらに、C++ 03より新しい標準をサポートしていない一部のツールには制限があるため、ヘッダーに次のコードがあるとします。

#if __cplusplus <= 199711L
    #define nullptr (0)
    #include <stdint.h>
#else
    #include <cstdint>
#endif // End if C++03

私のコンパイラは警告やエラーなしでこれをビルドします。私はnullptrをキャストするhaveしていないことを知っていますが、私には説得力のある理由がありますすべきしますそれ?つまり、Foo()を使用するとif (b == static_cast<Bar*>(nullptr))を使用すると回避できたおよびコンパイラが警告しなかったいくつかのバグが潜む可能性がありますか私について(C++ 03またはC++ 11以降)

キャストを避ける理由は次のとおりです。

  1. nullptrを使用するたびにキャストを追加すると、コードが乱雑になり、読みにくくなります。
  2. そうするコードは(あるとしても)あまり見かけません。

番号2はそれ自体は正当な理由ではないので、コードの作成者にとってより便利なためか、そうする必要がある理由が本当にないためにそうなったのかと思います。

提案された回答に基づいて編集:質問は次のとおりです。

  1. 私が今C++ 03で立ち往生しているが、将来的にC++ 11を計画したい場合は、レガシーNULLを整数値に設定し、すべてのそれに伴う慣行?
  2. #define NULL (0)の種類に行き詰まっている場合、常にキャストを適用する必要がありますか?例:if(b == static_cast<Bar*>(NULL))はあまり実行されていないようで、これが怠惰なのか、または比較の際にこれを実行するか、実行しない理由があるのか​​と疑問に思っています(上記のヌルポインターチェックのように)。
5
CodingHero

さらに、C++ 03より新しい標準をサポートしていない一部のツールには制限があるため、ヘッダーに次のコードがあるとします。

これは非常に悪い考えです。

式_(0)_は、(多かれ少なかれ)NULLのC++定義と同等です。問題は、nullptrNULLの欠点に対処するために特別に開発されたということです。

したがって、それらが何らかの形で同等であると偽ると、読者は混乱するだけです。 C++ 03コンパイラでコンパイルすると、動作が異なるコードをC++ 11に慣れている人々にそれを提供します。例えば:

_void foo(int);
void foo(Bar*);

foo(nullptr);
_

C++ 11は、これがmust call foo(Bar*)であることを通知します。ただし、C++ 03マクロは代わりにfoo(int)を呼び出します。 foo(NULL)でも同じ問題が発生するため、nullptrはそれを阻止するために開発されました。

つまり、C++ 03コードにのように見える C++ 11コードがあるが、-動作が異なるのはひどい考えです。

nullptr、設計上、特定のポインター型にキャストする必要はほとんどありません。唯一の例外は、次のようなフォームの関数を呼び出す場合です。

_template<typename T>
void foo(T* p);
_

ただし、その場合でも、foo<ActualType>(nullptr)を使用するだけで、foo(static_cast<ActualType*>(nullptr))と同じ効果を得ることができます。

Not -nullptrは、NULLと同じ状況でキャストする必要があります。実際、これは基本的にNULLと同等であるため、NULLを使用する必要があります。したがって、NULLが持っているすべての警告があります。

そして参考までに:C++ 11の_nullptr_t_型と同じ動作をする型をC++ 03で作成することはほとんど不可能です。暗黙の変換などを使用して、接近することができます。しかし、それがうまくいかない場合は常にあります。

したがって、確実ではないnullptrの有望な動作を停止します。

22
Nicol Bolas