Selon le projet de norme N4713 (7.11/1):
Une constante de pointeur nul est un littéral entier (5.13.2) de valeur zéro ou une valeur de type
std::nullptr_t
.
et 21.2.3/2:
La macro
NULL
est une constante de pointeur nul définie par l'implémentation.
suivez que NULL
peut être défini comme nullptr
. La même chose est mentionnée sur cppreference :
#define NULL 0
//since C++11
#define NULL nullptr
En même temps, la clause "Opérateurs additifs" dit (8.5.6/7):
Si la valeur
0
est ajouté ou soustrait d'une valeur de pointeur nulle, le résultat est une valeur de pointeur nulle. Si deux valeurs de pointeur nul sont soustraites, le résultat est égal à la valeur0
converti en typestd::ptrdiff_t
.
Par conséquent, le code suivant doit être valide:
0 + nullptr;
nullptr - nullptr;
mais en raison du manque d'opérateurs +/- pour std::nullptr_t
le le code n'est pas valide .
Y a-t-il quelque chose que je n'ai pas pris en compte ou la macro NULL
ne peut pas être réellement définie comme nullptr
?
Alors que nullptr
est une constante de pointeur nul , ce n'est pas une valeur de pointeur nul . Ce dernier est une valeur d'un type de pointeur, qui std::nullptr_t
n'est pas.
Référence:
Une constante de pointeur nul est un littéral entier (5.13.2) de valeur zéro ou une valeur de type
std::nullptr_t
. ne constante de pointeur nul peut être convertie en un type de pointeur; le résultat est la valeur de pointeur nulle de ce type et se distingue de toutes les autres valeurs du pointeur d'objet ou du type de pointeur de fonction. Une telle conversion est appelée conversion de pointeur nul. [...]
7.11/1 dans N4659, accentuez le mien
Donc NULL
peut en effet être nullptr
sans fournir les opérateurs arithmétiques.
nullptr
est un littéral de pointeur nul, et bien que le résultat de la conversion de nullptr
en type de pointeur soit la valeur du pointeur nul, nullptr
lui-même n'est pas de type pointeur, mais de type std::nullptr_t
. L'arithmétique fonctionne si vous convertissez le nullptr
en un type de pointeur:
0 + (int*)nullptr;
(int*)nullptr - (int*)nullptr;
La macro NULL peut-elle réellement être un nullptr?
Oui, car nullptr
est un littéral de pointeur nul.
Notez qu'avant C++ 11, tous les littéraux de pointeur null en C++ se trouvaient également être des littéraux entiers, donc ce mauvais code: char c = NULL;
avait l'habitude de travailler dans la pratique. Si NULL
est défini comme nullptr
, ce code ne fonctionne plus.
De plus, soit les deux opérandes doivent avoir un type d'énumération arithmétique ou non étendue, ou un opérande doit être un pointeur vers un type d'objet complètement défini et l'autre doit avoir un type d'énumération intégral ou non étendu.
Pour la soustraction, l'un des éléments suivants doit être respecté:
(2.1) les deux opérandes ont un type d'énumération arithmétique ou non étendue; ou
(2.2) les deux opérandes sont des pointeurs vers des versions qualifiées cv ou non cv du même type d'objet complètement défini; ou
(2.3) l'opérande de gauche est un pointeur vers un type d'objet complètement défini et l'opérande de droite a un type d'énumération intégrale ou non.
std::nullptr_t
n'en fait pas partie, donc std::nullptr
ne peut pas participer aux opérations additives.
Notez que même toutes les valeurs de pointeur ne peuvent pas participer. Par exemple, les valeurs de pointeur de fonction et les valeurs de pointeur vide ne peuvent pas, même si l'une ou l'autre peut être une valeur de pointeur nulle.
Le mot clé nullptr
désigne le littéral du pointeur. Il s'agit d'un prvalue
de type std::nullptr_t
. Il existe des conversions implicites de nullptr
en valeur de pointeur nulle de tout type de pointeur et de tout pointeur en type de membre. nullptr
lui-même n'est pas une valeur de pointeur ni un pointeur. Les opérations arithmétiques ne sont donc pas applicables à nullptr
.