¿Qué es exactamente nullptr?

10 minutos de lectura

¿Que es exactamente nullptr
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?

  • 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 devuelve nullptr_tentonces 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 a nullptr porque el tipo se define como typedef 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 capturar nullptr, 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

¿Que es exactamente nullptr
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_ty 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_casty 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*).

  • Oh, después de mirar, me parece que el operador condicional no puede convertir 0 a nullptr en casos como cond ? nullptr : 0;. Eliminado de mi respuesta.

    – Johannes Schaub – litb

    15 de agosto de 2009 a las 17:23

  • Tenga en cuenta que NULL ni siquiera está garantizado que sea 0. Puede ser 0Len cuyo caso una llamada a void f(int); void f(char *); será ambiguo. nullptr siempre favorecerá la versión del puntero, y nunca llamará a la int una. También tenga en cuenta que nullptr es convertible a bool (el borrador dice que en 4.12).

    – Johannes Schaub – litb

    15 de agosto de 2009 a las 18:09

  • @litb: entonces, con respecto a f (int) y f (void *), ¿f (0) seguirá siendo ambiguo?

    – Steve locura

    15 de agosto de 2009 a las 20:48

  • @Steve, no, eso llamará al int versión. Pero f(0L) es ambiguo, porque long -> int así como también long -> void* ambos son igualmente costosos. Entonces, si NULL es 0L en su compilador, luego una llamada f(NULL) será ambiguo dadas esas dos funciones. No es así con nullptr por supuesto.

    – Johannes Schaub – litb

    15 de agosto de 2009 a las 22:14

  • @SvenS No debe definirse como (void*)0 en C++. Pero se puede definir como cualquier constante arbitraria de puntero nulo, que cualquier constante integral con valor 0 y nullptr realizar. Entonces, definitivamente no voluntad pero lata. (Olvidaste enviarme un ping por cierto…)

    – Deduplicador

    24 de febrero de 2016 a las 1:31

¿Que es exactamente nullptr
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_tque es simplemente un typedef de decltype(nullptr)como se muestra aquí:

Definido en el encabezado <cstddef>:

Ver:

  1. https://en.cppreference.com/w/cpp/types/nullptr_t
  2. 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:

  1. Cprogramming.com: mejores tipos en C++ 11: nullptr, clases de enumeración (enumeraciones fuertemente tipadas) y cstdint
  2. https://en.cppreference.com/w/cpp/language/decltype
  3. https://en.cppreference.com/w/cpp/types/nullptr_t
  4. https://en.cppreference.com/w/cpp/header/cstddef
  5. https://en.cppreference.com/w/cpp/keyword/using
  6. https://en.cppreference.com/w/cpp/keyword/typedef

1647553520 80 ¿Que es exactamente nullptr
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:

  • C++09? ¿No se lo conocía como C++ 0x antes de agosto de 2011?

    – Michael Dorst

    12/03/2013 a las 19:10

  • @anthropomorphic Bueno, ese es su propósito. C++0x se usó mientras aún estaba en proceso, porque no se sabía si estaría terminado en 2008 o 2009. Tenga en cuenta que en realidad se convirtió en C++0B, lo que significa C++11. Ver stroustrup.com/C++11FAQ.html

    – mxmlnkn

    14 de abril de 2016 a las 9:59


1647553521 100 ¿Que es exactamente nullptr
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)  {  }

1647553522 370 ¿Que es exactamente 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.

  • Tenga en cuenta que esta respuesta es incorrecta. NULL no se garantiza que se amplíe a 0.

    – LF

    4 de julio de 2019 a las 7:26

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).

  • Tenga en cuenta que esta respuesta es incorrecta. NULL no se garantiza que se amplíe a 0.

    – LF

    4 de julio de 2019 a las 7:26

1647553523 95 ¿Que es exactamente nullptr
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

  • No veo cómo mejora esto cuando uso nullptr (y C++ 11). Si establece pb en nullptr, la primera comparación sigue siendo verdadera (al comparar manzanas con peras…). El segundo caso es aún peor: si compara a con nullptr, convertirá a en B* y luego se evaluará como verdadero nuevamente (antes de que se convirtiera en bool y la expresión se evaluara como falsa). Todo me recuerda a JavaScript y me pregunto si obtendremos === en C++ en el futuro 🙁

    – ceros

    25 de abril de 2018 a las 11:01

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad