web-dev-qa-db-fra.com

Quelle est la différence entre NULL et __null en C ++?

J'ai le code suivant:

MyType x = NULL;

NetBeans m'a suggéré de le changer en ceci:

MyType x = __null;

J'ai cherché et trouvé que __null S'appelle un "mot clé du compilateur", ce qui, je suppose, signifie qu'il est utilisé en interne pour le compilateur. Je ne comprends pas pourquoi NetBeans a suggéré de le remplacer par un mot clé du compilateur.

Quelle est la différence entre NULL et __null En c ++?

__null est un g++ chose interne qui sert à peu près au même objectif que la norme nullptr ajoutée dans C++ 11 (agissant de manière cohérente comme un pointeur, jamais comme un entier).

NULL est défini comme 0, qui peut être utilisé implicitement comme un entier, un booléen, une valeur à virgule flottante ou un pointeur, ce qui pose un problème pour la résolution de la surcharge, lorsque vous souhaitez appeler la fonction prenant spécifiquement un pointeur.

En tout état de cause, vous ne devez pas utiliser __null parce que c'est un g++ détail de la mise en œuvre, son utilisation garantit donc un code non portable. Si vous pouvez compter sur C++ 11 (vous le pouvez sûrement maintenant?), Utilisez nullptr. Sinon, NULL est votre seule option portable.

53
ShadowRanger

NULL a été dépassé de C en C++ et - avant C++ 11 - a adopté sa signification en C:

jusqu’à C++ 11: la macro NULL est une constante de pointeur null définie par l’implémentation, qui peut être une expression de constante intégrale rvalue de type entier évaluée à zéro.

C++ 11 a ensuite introduit un littéral de pointeur null dédié nullptr de type std::nullptr_t. Mais, probablement pour des raisons de compatibilité, la macro NULL n'a pas été supprimée; sa définition était juste un peu détendue en ce que les compilateurs peuvent maintenant le définir soit comme type intégral ou comme type de pointeur:

C++ 11: un littéral entier de valeur zéro ou une prvalue de type std :: nullptr_t

Si vous utilisez NULL, vous obtenez un comportement défini par l'implémentation en résolution de surcharge. Considérons, par exemple, le code suivant avec un compilateur qui utilise la version intégrale de la macro NULL-. Ensuite, un appel utilisant NULL comme paramètre transmis à une fonction peut créer des ambiguïtés:

struct SomeOverload {

    SomeOverload(int x) {
        cout << "taking int param: " << x << endl;
    }
    SomeOverload(void* x) {
        cout << "taking void* param: " << x << endl;
    }
};

int main() {

    int someVal = 10;

    SomeOverload a(0);
    SomeOverload b(&someVal);

    // SomeOverload c(NULL);  // Call to constructor is ambiuous
    SomeOverload d(nullptr);
}

Il est donc recommandé d’utiliser nullptr où vous souhaitez exprimer le type de pointeur.

Et n'utilisez pas __null, car il s'agit d'une constante non portable spécifique au compilateur; nullptr, en revanche, est parfaitement portable.

11
Stephan Lechner

NULL est l'ancien symbole C pour un pointeur nul. C++ a traditionnellement utilisé 0 pour les pointeurs nuls et depuis le standard C++ 11 nullptr.

Étant donné que x ne semble pas être un pointeur, vous ne pouvez pas initialiser x pour qu'il soit un pointeur nul, et le __null symbol est peut-être un symbole interne au compilateur pour un null valeur (qui est un concept qui n'existe pas vraiment en C++ standard).

Si vous souhaitez que x soit initialisé à un état par défaut, vous devez vous appuyer sur le constructeur MyClass default pour initialiser les objets et ses variables membres à des valeurs par défaut appropriées.

8