
Khaled Alshaya
Ahora tenemos C++ 11 con muchas características nuevas. Una interesante y confusa (al menos para mí) es la nueva nullptr
.
Bueno, ya no necesitas la macro desagradable. NULL
.
int* x = nullptr;
myclass* obj = nullptr;
Aún así, no entiendo cómo nullptr
obras. Por ejemplo, artículo de wikipedia dice:
C++11 corrige esto introduciendo un nuevo palabra clave para servir como una constante distinguida de puntero nulo: nullptr. es de escriba nullptr_t, que es implícitamente convertible y comparable a cualquier tipo de puntero o tipo de puntero a miembro. No es implícitamente convertible ni comparable a los tipos integrales, excepto bool.
¿Cómo es una palabra clave y una instancia de un tipo?
Además, ¿tiene otro ejemplo (además del de Wikipedia) donde nullptr
es superior al buen viejo 0
?

Johannes Schaub – litb
¿Cómo es una palabra clave y una instancia de un tipo?
Esto no es sorprendente. Ambas cosas true
y false
son palabras clave y como literales tienen un tipo ( bool
). nullptr
es un puntero literal de tipo std::nullptr_t
y es un prvalue (no puede tomar la dirección usando &
).
-
4.10
sobre la conversión de puntero dice que un prvalue de tipo std::nullptr_t
es una constante de puntero nulo, y que una constante de puntero nulo integral se puede convertir en std::nullptr_t
. La dirección opuesta no está permitida. Esto permite sobrecargar una función tanto para punteros como para enteros, y pasar nullptr
para seleccionar la versión del puntero. Paso NULL
o 0
seleccionaría confusamente el int
versión.
-
un elenco de nullptr_t
a un tipo integral necesita un reinterpret_cast
y tiene la misma semántica que un elenco de (void*)0
a un tipo integral (definición de implementación de mapeo). A reinterpret_cast
no se puede convertir nullptr_t
a cualquier tipo de puntero. Confíe en la conversión implícita si es posible o use static_cast
.
-
La Norma exige que sizeof(nullptr_t)
ser sizeof(void*)
.

grapas gabriel
¿Por qué nullptr en C++ 11? ¿Qué es? ¿Por qué NULL no es suficiente?
experto en C++ Alex Allain lo dice perfectamente aquí (énfasis mío añadido en negrita):
… imagina que tienes las dos declaraciones de funciones siguientes:
void func(int n);
void func(char *s);
func( NULL ); // guess which function gets called?
Aunque parece que se llamará a la segunda función (después de todo, está pasando lo que parece ser un puntero), ¡realmente se llamará a la primera función! El problema es que debido a que NULL es 0 y 0 es un número entero, en su lugar se llamará a la primera versión de func. Este es el tipo de cosa que, sí, no sucede todo el tiempo, pero cuando sucede, es extremadamente frustrante y confuso. Si no conoce los detalles de lo que está sucediendo, podría parecer un error del compilador. Una característica del lenguaje que parece un error del compilador es, bueno, algo que no desea.
Ingrese punto nulo. En C++11, nullptr es una nueva palabra clave que puede (¡y debe!) usarse para representar punteros NULL; en otras palabras, dondequiera que haya escrito NULL antes, debe usar nullptr en su lugar. No está más claro para ti, el programador.(todos saben lo que significa NULL), pero es más explícito para el compiladorque ya no verá ceros en todas partes para tener un significado especial cuando se use como puntero.
Allain termina su artículo con:
Independientemente de todo esto, la regla general para C++ 11 es simplemente comenzar a usar nullptr
cada vez que hubieras usado NULL
en el pasado.
(Mis palabras):
Por último, no olvides que nullptr
es un objeto, una clase. Se puede usar en cualquier lugar NULL
se usó antes, pero si necesita su tipo por alguna razón, su tipo se puede extraer con decltype(nullptr)
o descrito directamente como std::nullptr_t
que es simplemente un typedef
de decltype(nullptr)
como se muestra aquí:
Definido en el encabezado <cstddef>
:
Ver:
- https://en.cppreference.com/w/cpp/types/nullptr_t
- y https://en.cppreference.com/w/cpp/header/cstddef
namespace std
{
typedef decltype(nullptr) nullptr_t; // (since C++11)
// OR (same thing, but using the C++ keyword `using` instead of the C and C++
// keyword `typedef`):
using nullptr_t = decltype(nullptr); // (since C++11)
} // namespace std
Referencias:
- Cprogramming.com: mejores tipos en C++ 11: nullptr, clases de enumeración (enumeraciones fuertemente tipadas) y cstdint
- https://en.cppreference.com/w/cpp/language/decltype
- https://en.cppreference.com/w/cpp/types/nullptr_t
- https://en.cppreference.com/w/cpp/header/cstddef
- https://en.cppreference.com/w/cpp/keyword/using
- https://en.cppreference.com/w/cpp/keyword/typedef

Nik
Desde nullptr: un puntero nulo de tipo seguro y claro:
La nueva palabra clave nullptr de C++09 designa una constante rvalue que sirve como un literal de puntero nulo universal, reemplazando el literal 0 defectuoso y débilmente tipado y la infame macro NULL. nullptr pone así fin a más de 30 años de vergüenza, ambigüedad y errores. Las siguientes secciones presentan la función nullptr y muestran cómo puede remediar las dolencias de NULL y 0.
Otras referencias:

Motti
Cuando tiene una función que puede recibir punteros a más de un tipo, llamándola con NULL
es ambiguo. La forma en que esto se soluciona ahora es muy complicada al aceptar un int y asumir que es NULL
.
template <class T>
class ptr {
T* p_;
public:
ptr(T* p) : p_(p) {}
template <class U>
ptr(U* u) : p_(dynamic_cast<T*>(u)) { }
// Without this ptr<T> p(NULL) would be ambiguous
ptr(int null) : p_(NULL) { assert(null == NULL); }
};
En C++11
serías capaz de sobrecargar nullptr_t
así que eso ptr<T> p(42);
sería un error en tiempo de compilación en lugar de un tiempo de ejecución assert
.
ptr(std::nullptr_t) : p_(nullptr) { }

usuario633658
nullptr
no se puede asignar a un tipo integral como un int
pero solo un tipo de puntero; ya sea un tipo de puntero incorporado como int *ptr
o un puntero inteligente como std::shared_ptr<T>
Creo que esta es una distinción importante porque NULL
todavía se puede asignar tanto a un tipo integral como a un puntero como NULL
es una macro expandida a 0
que puede servir tanto como un valor inicial para un int
así como un puntero.
Bueno, otros idiomas tienen palabras reservadas que son instancias de tipos. Pitón, por ejemplo:
>>> None = 5
File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>
Esta es en realidad una comparación bastante cercana porque None
se usa típicamente para algo que no ha sido inicializado, pero al mismo tiempo comparaciones como None == 0
son falsos
Por otro lado, en el plano C, NULL == 0
devolvería verdadero IIRC porque NULL
es solo una macro que devuelve 0, que siempre es una dirección no válida (AFAIK).

el cerdo
Además, ¿tiene otro ejemplo (además del de Wikipedia) donde nullptr
es superior al buen viejo 0?
Si. También es un ejemplo (simplificado) del mundo real que ocurrió en nuestro código de producción. Solo se destacó porque gcc pudo emitir una advertencia al realizar una compilación cruzada en una plataforma con un ancho de registro diferente (todavía no estoy seguro exactamente por qué solo cuando se realiza una compilación cruzada de x86_64 a x86, advierte warning: converting to non-pointer type 'int' from NULL
):
Considere este código (C++03):
#include <iostream>
struct B {};
struct A
{
operator B*() {return 0;}
operator bool() {return true;}
};
int main()
{
A a;
B* pb = 0;
typedef void* null_ptr_t;
null_ptr_t null = 0;
std::cout << "(a == pb): " << (a == pb) << std::endl;
std::cout << "(a == 0): " << (a == 0) << std::endl; // no warning
std::cout << "(a == NULL): " << (a == NULL) << std::endl; // warns sometimes
std::cout << "(a == null): " << (a == null) << std::endl;
}
Produce esta salida:
(a == pb): 1
(a == 0): 0
(a == NULL): 0
(a == null): 1
hecho relacionado:
nullptr
también se usa para representar referencias nulas para identificadores administrados en C++/CLI.– mmx
15 de agosto de 2009 a las 16:52
Es
nullptr_t
garantizado tener un solo miembro,nullptr
? Entonces, si una función devuelvenullptr_t
entonces el compilador ya sabe qué valor se devolverá, independientemente del cuerpo de la función.– Aaron McDaid
28 de julio de 2015 a las 11:02
@AaronMcDaid
std::nullptr_t
se pueden instanciar, pero todas las instancias serán idénticas anullptr
porque el tipo se define comotypedef decltype(nullptr) nullptr_t
. Creo que la razón principal por la que existe el tipo es para que las funciones se puedan sobrecargar específicamente para capturarnullptr
, si necesario. Ver aquí para un ejemplo.– Justin Time – Reincorporar a Monica
14 de junio de 2016 a las 23:26
0 nunca fue un puntero nulo, el puntero nulo es un puntero que se puede obtener fundición cero literal al tipo de puntero, y no apunta a ninguna objeto existente por definición.
– Swift – Pastel de viernes
6 de marzo de 2017 a las 7:26
@Nils ¡El punto es expresar la intención!
– chico curioso
8 de julio de 2019 a las 1:06