Este trozo de código conceptualmente hace lo mismo para los tres punteros (seguro puntero de inicialización):

int* p1 = nullptr;
int* p2 = NULL;
int* p3 = 0;

Y así, ¿cuáles son las ventajas de la asignación de punteros nullptr sobre la asignación de los valores NULL o 0?

  • Por un lado, una función sobrecargada de tomar int y void * no se elige el int versión sobre la void * versión cuando se utiliza nullptr.
  • Bien f(nullptr) es diferente de f(NULL). Pero como ahora ya que el código anterior es que se trate(la asignación a una variable local), de los tres punteros son exactamente los mismos. La única ventaja es la legibilidad del código.
  • Yo estoy a favor de hacer de este un FAQ, @Prasoon. Gracias!
  • NB NULL es, históricamente, no se garantiza que sea 0, pero es como oc C99, en la misma manera que un byte, no necesariamente era de 8 bits de longitud y verdadero y lo falso se arquitectura dependiente de los valores. Esta pregunta se centra en nullptr butthat es la diferencia entre el 0 y el NULL
InformationsquelleAutor Mark Garcia | 2012-12-11

7 Comentarios

  1. 172

    En ese código, no parece ser una ventaja. Pero considere las siguientes funciones sobrecargadas:

    void f(char const *ptr);
    void f(int v);
    
    f(NULL);  //which function will be called?

    Que la función se llama? Por supuesto, aquí la intención es llamar f(char const *), pero en realidad f(int) será llamado! Ese es un gran problema1 ¿no?

    Así, la solución a estos problemas es el uso de nullptr:

    f(nullptr); //first function is called

    De curso, que no es la única ventaja de nullptr. Aquí es otro:

    template<typename T, T *ptr>
    struct something{};                     //primary template
    
    template<>
    struct something<nullptr_t, nullptr>{};  //partial specialization for nullptr

    Ya que en la plantilla, el tipo de nullptr se deduce como nullptr_t, así que usted puede escribir esto:

    template<typename T>
    void f(T *ptr);   //function to handle non-nullptr argument
    
    void f(nullptr_t); //an overload to handle nullptr argument!!!

    1. En C++, NULL se define como #define NULL 0, por lo que es básicamente int, que es la razón por la f(int) se llama.

    • No veo que tipo de sobrecarga en la práctica muy a menudo, pero sí….
    • Como lo Mehrdad había indicado, estos tipos de sobrecargas son bastante raros. Hay otras ventajas importantes de nullptr? (No. Yo no soy exigente)
    • Ver la edición.
    • Bueno, sinceramente, no sé lo que something es ;). De niza.
    • Esperar. ¿Por qué quiero tener something<nullptr_t, nullptr> sumThing?
    • Esto puede ser de ayuda: stackoverflow.com/questions/13665349/…
    • Uno podría necesitar something<nullptr_t, nullptr> especialmente en la plantilla de metaprogramación.
    • Su nota a pie de página se parece al revés. NULL es requerido por la norma para tener un tipo integral, y por eso es que normalmente se define como 0 o 0L. También no estoy seguro de que me gusta que nullptr_t de sobrecarga, ya que las capturas de solo llamadas con nullptr, no con un puntero nulo de un tipo diferente, como (void*)0. Pero puedo creer que algunos de los usos que, incluso si todo lo que hace es guardar la definición de un valor único lugar-tipo de titular de su propio significa «ninguno».
    • Otra ventaja (aunque hay que reconocer que los menores de edad) puede ser que nullptr tiene una bien definida valor numérico mientras que el puntero null constantes no. Un puntero nulo constante se convierte en el puntero nulo de ese tipo (lo que es). Es necesario que los dos punteros null del mismo tipo comparar de forma idéntica, y booleano conversión se convierte en un puntero nulo en false. no se requiere Nada más. por lo Tanto, es posible que un compilador (tonto, pero es posible) para que use, por ejemplo, 0xabcdef1234 o algún otro número para el puntero null. Por otro lado, nullptr es necesario para convertir a cero.
    • En un segundo pensamiento, «tonto» no es tan tontos a todos. Un compilador podría utilizar distintos valores de puntero nulo para cada tipo (en un rango de direcciones que sin duda violación de segmento), por lo que un manejador de errores o el depurador puede saber inmediatamente el tipo de un sin referencia a un puntero nulo sólo por la raw de la dirección. Esto no sólo no es «tonto», pero en realidad son muy cool.
    • Eres lo que implica que NULL podría tener un valor distinto de 0?
    • Esto es incorrecto. La verdadera motivación fue la necesidad de reenvío. Este caso trivial puede ser resuelto por un elenco.
    • Lo que es incorrecto en mi respuesta? que f(nullptr) no llamar a la función? Había más de uno motivaciones. Muchas otras cosas útiles pueden ser descubiertas por los propios programadores en los próximos años. Así que usted no puede decir que no es un único y verdadero uso de nullptr.
    • También, el downvoting es tonta, aunque mi respuesta no hablar de la los de la motivación. Es como downvoting una respuesta en la que habla acerca de las plantillas de C++ metaprogramación, dando una tonta razón por la que la plantilla «NO fue añadido a hacer metaprogramación» (sí, fue DISCOVORED).
    • Sí, por supuesto. La norma dice que los nulos los literales son equivalentes a un valor numérico de cero (literales, no es el asignado a los punteros!), y que se convierten en el puntero nulo del respectivo tipo. Hay restricciones adicionales (ver arriba), pero no dice que el puntero nulo de un tipo que debe tener cualquier valor numérico. De hecho, afirmando que nullpointers de igual tipo comparar la igualdad, es explícitamente no se garantiza que dos punteros null de diferentes tipos de comparar la igualdad. Por lo tanto, si int* a=0; char* b=0; assert(a == b); falla, que no es totalmente admisible.
    • Ok, no es permisible para comparar los punteros como este… pero usted consigue la idea. Si los lanzas a enteros por lo compila, la aserción puede fallar.
    • No, NULL no puede ser cualquier valor distinto de 0. Debe ser cero. Quien dijo «no es permisible para comparar los punteros como este»? Usted puede comparar punteros.
    • La comparación de distintos tipos de puntero de la manera que lo hice anteriormente no está permitido (no sin fundición, de todos modos), por lo que no compile, pero eso es irrelevante para lo que yo estaba diciendo (la adición de un molde para intptr_t no han de caber en un comentario de todos modos). Acerca de NULL y nullptr, tenga en cuenta que son cosas diferentes. NULL es una macro para 0, un literal entero que se convierte implícitamente a un puntero nulo (no nullptr) valor. Y eso, ciertamente, puede de ser algo distinto a cero. No se especifica lo que el valor de un puntero nulo de algún tipo, lo que si es cero, la conveniencia o la suerte.
    • La nota de pie de página necesidades de corrección. En C++ NULL tiene un valor definido por la implementación, con las definiciones posibles que puede 0 o 0L.
    • Es esto realmente supone template<typename T, T *ptr> struct something {};, o más bien template<typename T, T ptr> ... (sin el *)?
    • Ambos trabajarán. nullptr puede inicializar nullptr_t y nullptr_t*!!! Por qué utiliza T*, porque quería demostrar el puntero semántica. Consulte este … y este. Agradezco tu comentario por CIERTO. 🙂
    • Ah, por supuesto!
    • Te refieres al ejemplo dado definiciones para NULL son 0 y 0L. Tan sólo debe ser un apuntador null constante convertir implícitamente a cualquier tipo de puntero. nullptr se ajusta a la ley.

  2. 84

    C++11 introduce nullptr, es conocido como el Null puntero constante y Se mejora de la seguridad de tipos y resuelve situaciones ambiguas a diferencia de la existente depende de la implementación de puntero nulo constante NULL. Para ser capaces de entender las ventajas de nullptr. primero tenemos que entender lo que es NULL y cuáles son los problemas asociados con ella.


    Lo que es NULL exactamente?

    Pre C++11 NULL fue usado para representar un puntero que no tiene ningún valor o puntero que no apunta a nada válido. Contrariamente a la creencia popular NULL no es una palabra clave de C++. Es un identificador definido en la biblioteca estándar de los encabezados. En resumen, usted no puede utilizar NULL sin incluir algunos de la biblioteca estándar de los encabezados. Considerar la Programa de ejemplo:

    int main()
    { 
        int *ptr = NULL;
        return 0;
    }

    De salida:

    prog.cpp: In function 'int main()':
    prog.cpp:3:16: error: 'NULL' was not declared in this scope

    El estándar de C++ define NULL como una implementación de macro definido definido en el estándar de la biblioteca de archivos de encabezado.
    El origen de NULL es de C y C++ heredado de C. El C estándar define NULL como 0 o (void *)0. Pero en C++ hay una sutil diferencia.

    C++ no podía aceptar esta especificación como es. A diferencia de C, C++ es un lenguaje con establecimiento inflexible (C no requiere la conversión explícita de void* de cualquier tipo, mientras que C++ exige una conversión explícita). Esto hace que la definición de NULL especificado por el estándar de C inútil en muchos C++ expresiones. Por ejemplo:

    std::string * str = NULL;         //Case 1
    void (A::*ptrFunc) () = &A::doSomething;
    if (ptrFunc == NULL) {}           //Case 2

    Si es NULL se define como (void *)0, ninguna de las expresiones anteriores iba a funcionar.

    • Caso 1: no compila porque una fundición automática, es necesario partir de void * a std::string.
    • Caso 2: no compila porque elenco de void * a puntero a función miembro es necesario.

    Así, a diferencia de C, C++ Estándar, el mandato de definir NULL como literal numérico 0 o 0L.


    Entonces, ¿cuál es la necesidad de otro puntero nulo constante cuando tenemos NULL ya?

    Pesar de que el comité de Estándares de C++ se acercó con un NULL definición que trabajará para C++, esta definición tenía su propia cuota de problemas. NULL funcionado lo suficientemente bien como para casi todos los escenarios, pero no todos. Se dio sorprendente y resultados erróneos para ciertos escenarios poco comunes. Por ejemplo:

    #include<iostream>
    void doSomething(int)
    {
        std::cout<<"In Int version";
    }
    void doSomething(char *)
    {
       std::cout<<"In char* version";
    }
    
    int main()
    {
        doSomething(NULL);
        return 0;
    }

    De salida:

    In Int version

    Claramente, la intención parece ser la de llamar a la versión que lleva char* como el argumento, sino como el resultado muestra la función que toma un int versión se llama. Esto es debido a que NULL es un literal numérico.

    Además, como es definida por implementación NULL si es 0 o 0 L, hay mucha confusión en función de la resolución de sobrecarga.

    Programa De Ejemplo:

    #include <cstddef>
    
    void doSomething(int);
    void doSomething(char *);
    
    int main()
    {
      doSomething(static_cast <char *>(0));    //Case 1
      doSomething(0);                          //Case 2
      doSomething(NULL)                        //Case 3
    }

    Analizar el fragmento anterior:

    • Caso 1: llamadas doSomething(char *) como se esperaba.
    • Caso 2: llamadas doSomething(int) pero tal vez char* versión era deseable porque 0 también ES un puntero null.
    • Caso 3: Si NULL se define como 0, llamadas doSomething(int) cuando tal vez doSomething(char *) fue la intención, quizás el resultado en el error lógico en tiempo de ejecución. Si NULL se define como 0L, la llamada es ambiguo y los resultados en el error de compilación.

    Así, dependiendo de la aplicación, el mismo código se puede dar diferentes resultados, lo cual es claramente indeseable. Naturalmente, el comité de estándares de C++ querido corregir esto y que es la principal motivación para nullptr.


    Entonces, ¿qué es nullptr y cómo evitar los problemas de NULL?

    C++11 introduce una nueva palabra clave nullptr para servir como puntero nulo constante. A diferencia NULL, su comportamiento no es de aplicación definido. No es una macro pero tiene su propio tipo. nullptr tiene el tipo de std::nullptr_t. C++11 adecuadamente define las propiedades del nullptr para evitar las desventajas de NULL. Para resumir sus propiedades:

    Propiedad 1: tiene su propio tipo de std::nullptr_t, y

    Propiedad 2: es implícitamente convertible y comparable a cualquier tipo de puntero o un puntero-a-miembro tipo, pero

    Propiedad 3: no es convertible implícitamente o comparable a la de los tipos integrales, excepto para bool.

    Considere el siguiente ejemplo:

    #include<iostream>
    void doSomething(int)
    {
        std::cout<<"In Int version";
    }
    void doSomething(char *)
    {
       std::cout<<"In char* version";
    }
    
    int main()
    {
        char *pc = nullptr;      //Case 1
        int i = nullptr;         //Case 2
        bool flag = nullptr;     //Case 3
    
        doSomething(nullptr);    //Case 4
        return 0;
    }

    En el programa anterior,

    • Caso 1: OK – Propiedad 2
    • Caso 2: No Aceptar La Propiedad De 3
    • Caso 3: OK – Propiedad 3
    • Caso 4: Ninguna confusión – Llamadas char * versión, la Propiedad 2 & 3

    Por lo tanto la introducción de nullptr evita todos los problemas de la vieja y buena NULL.

    Cómo y dónde se debe utilizar nullptr?

    La regla del pulgar para C++11 es simplemente empezar a usar nullptr siempre que hubieran utilizado NULL en el pasado.



    Estándar De Referencias:

    C++11 Estándar: C. 3.2.4 Macro NULL

    C++11: 18.2 Tipos

    C++11: 4.10 Puntero conversiones

    Estándar C99: 6.3.2.3 Punteros

    • Yo ya estoy practicando su último consejo ya que he conocido a nullptr, aunque no sabía lo que diferencia realmente a mi código. Gracias por la gran respuesta y sobre todo por el esfuerzo. Me trajo una gran cantidad de luz sobre el tema.
    • «en cierto nivel de encabezado de la biblioteca de archivos.» -> ¿por qué no sólo tiene que escribir «cstddef» desde el principio?
    • ¿Por qué debemos permitir que nullptr a ser convertibles a tipo bool? Por favor podría elaborar más?
    • …fue usado para representar un puntero que no tiene ningún valor… Variables siempre tiene un valor. Puede ser el ruido, o 0xccccc...., pero, un valor de-menos variable es una contradicción inherente.
    • «Caso 3: OK – Propiedad 3» (línea bool flag = nullptr;). Nope, no ACEPTAR, me sale el siguiente error en tiempo de compilación con g++ 6: error: converting to ‘bool’ from ‘std::nullptr_t’ requires direct-initialization [-fpermissive]
  3. 23

    La verdadera motivación aquí es perfecto reenvío.

    Considerar:

    void f(int* p);
    template<typename T> void forward(T&& t) {
        f(std::forward<T>(t));
    }
    int main() {
        forward(0); //FAIL
    }

    Simplemente, 0 es un especial valor, pero los valores no se puede propagar a través del sistema – sólo los tipos de puede. Reenvío de funciones son esenciales, y 0 no se puede tratar con ellos. Por lo tanto, era absolutamente necesario introducir nullptr, donde el tipo es lo que es especial, y el tipo de hecho puede propagar. De hecho, el MSVC equipo tuvo que introducir nullptr antes de lo previsto después de que se implementa r-value referencias y, a continuación, descubrió este escollo para los mismos.

    Hay un par de casos de esquina donde nullptr puede hacer la vida más fácil – pero no es un núcleo caso, como un yeso puede resolver estos problemas. Considere la posibilidad de

    void f(int);
    void f(int*);
    int main() { f(0); f(nullptr); }

    Llamadas a separar los dos sobrecargas. Además, considere la posibilidad de

    void f(int*);
    void f(long*);
    int main() { f(0); }

    Este es ambiguo. Pero, con nullptr, puede proporcionar

    void f(std::nullptr_t)
    int main() { f(nullptr); }
    • Divertido. La mitad de la respuesta es la misma que la de los otros dos respuestas que según usted es «bastante incorrecta» respuestas!!!
    • El reenvío problema también puede resolverse con un yeso. forward((int*)0) obras. Me estoy perdiendo algo?
  4. 5

    Fundamentos de nullptr

    std::nullptr_t es el tipo de puntero nulo literal, nullptr. Es un prvalue/r-value de tipo std::nullptr_t. Existen conversiones implícitas de nullptr a puntero nulo valor de cualquier tipo de puntero.

    El literal 0 es un int, no es un puntero. Si C++ se encuentra a sí mismo mirando a 0, en un contexto donde sólo un puntero puede ser utilizado, que va a interpretar a regañadientes 0 como un puntero nulo, sino que es una posición de retroceso. C++’s principal de la política es la que 0 es un int, no es un puntero.

    Ventaja 1 – Quitar la ambigüedad cuando la sobrecarga de puntero y los tipos integrales

    En C++98, la principal implicación de este era que la sobrecarga en el puntero y los tipos integrales podría llevar a sorpresas. Paso 0 o NULL para tales sobrecargas nunca llamó a un puntero de sobrecarga:

       void fun(int); //two overloads of fun
        void fun(void*);
        fun(0); //calls f(int), not fun(void*)
        fun(NULL); //might not compile, but typically calls fun(int). Never calls fun(void*)

    La cosa interesante acerca de la llamada es la contradicción entre el significado aparente de la fuente de código («estoy llamando a la diversión con NULL null pointer») y su significado («estoy llamando a la diversión con algún tipo de entero— no el puntero null»).

    nullptr la ventaja es que no tienen un tipo integral.
    Llamar a la función sobrecargada de diversión con nullptr llama al vacío* sobrecarga (es decir, el puntero de sobrecarga), porque nullptr no puede ser visto como algo integral:

    fun(nullptr); //calls fun(void*) overload 

    Utilizando nullptr en lugar de 0 o NULO, por consiguiente, evita la sobrecarga de la resolución de sorpresas.

    Otra ventaja de nullptr más de NULL(0) cuando se utiliza el auto para el tipo de devolución de

    Por ejemplo, supongamos que encuentro esta en una base de código:

    auto result = findRecord( /* arguments */ );
    if (result == 0) {
    ....
    }

    Si usted no sabe (o no puede encontrar fácilmente) lo buscarregistro devuelve, puede no estar claro si el resultado es un puntero de tipo o de un tipo integral. Después de todo, 0 (¿qué resultado se prueba en contra) podría ir en cualquier dirección. Si ve el siguiente, en el otro lado,

    auto result = findRecord( /* arguments */ );
    if (result == nullptr) {
    ...
    }

    no hay ambigüedad: el resultado debe ser un tipo de puntero.

    Ventaja 3

    #include<iostream>
    #include <memory>
    #include <thread>
    #include <mutex>
    using namespace std;
    int f1(std::shared_ptr<int> spw) //call these only when
    {
      //do something
      return 0;
    }
    double f2(std::unique_ptr<int> upw) //the appropriate
    {
      //do something
      return 0.0;
    }
    bool f3(int* pw) //mutex is locked
    {
    
    return 0;
    }
    
    std::mutex f1m, f2m, f3m; //mutexes for f1, f2, and f3
    using MuxtexGuard = std::lock_guard<std::mutex>;
    
    void lockAndCallF1()
    {
            MuxtexGuard g(f1m); //lock mutex for f1
            auto result = f1(static_cast<int>(0)); //pass 0 as null ptr to f1
            cout<< result<<endl;
    }
    
    void lockAndCallF2()
    {
            MuxtexGuard g(f2m); //lock mutex for f2
            auto result = f2(static_cast<int>(NULL)); //pass NULL as null ptr to f2
            cout<< result<<endl;
    }
    void lockAndCallF3()
    {
            MuxtexGuard g(f3m); //lock mutex for f2
            auto result = f3(nullptr);//pass nullptr as null ptr to f3 
            cout<< result<<endl;
    } //unlock mutex
    int main()
    {
            lockAndCallF1();
            lockAndCallF2();
            lockAndCallF3();
            return 0;
    }

    Por encima de programa compila y ejecuta con éxito, pero lockAndCallF1, lockAndCallF2 & lockAndCallF3 tienen código redundante. Es lástima que escribir código como este si se puede escribir de la plantilla para que todos estos lockAndCallF1, lockAndCallF2 & lockAndCallF3. Así se puede generalizar con la plantilla. He escrito plantilla de función lockAndCall en lugar de la definición múltiple lockAndCallF1, lockAndCallF2 & lockAndCallF3 de código redundante.

    Código es re-factorizado como a continuación:

    #include<iostream>
    #include <memory>
    #include <thread>
    #include <mutex>
    using namespace std;
    int f1(std::shared_ptr<int> spw) //call these only when
    {
      //do something
      return 0;
    }
    double f2(std::unique_ptr<int> upw) //the appropriate
    {
      //do something
      return 0.0;
    }
    bool f3(int* pw) //mutex is locked
    {
    
    return 0;
    }
    
    std::mutex f1m, f2m, f3m; //mutexes for f1, f2, and f3
    using MuxtexGuard = std::lock_guard<std::mutex>;
    
    template<typename FuncType, typename MuxType, typename PtrType>
    auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))
    //decltype(auto) lockAndCall(FuncType func, MuxType& mutex, PtrType ptr)
    {
            MuxtexGuard g(mutex);
            return func(ptr);
    }
    int main()
    {
            auto result1 = lockAndCall(f1, f1m, 0); //compilation failed 
            //do something
            auto result2 = lockAndCall(f2, f2m, NULL); //compilation failed
            //do something
            auto result3 = lockAndCall(f3, f3m, nullptr);
            //do something
            return 0;
    }

    Detalle el análisis de por qué la compilación fallado por lockAndCall(f1, f1m, 0) & lockAndCall(f3, f3m, nullptr) no para lockAndCall(f3, f3m, nullptr)

    Por qué compilación de lockAndCall(f1, f1m, 0) & lockAndCall(f3, f3m, nullptr) fallado?

    El problema es que cuando se pasa 0 a lockAndCall, el tipo de plantilla de la deducción de patadas en la figura de su tipo. El tipo 0 es de tipo int, por lo que el tipo del parámetro ptr dentro de la creación de instancias de la presente convocatoria a lockAndCall. Desafortunadamente, esto significa que en la llamada a la función func dentro de lockAndCall, un int se le pasa, y que no es compatible con el std::shared_ptr<int> parámetro que f1 espera. El 0 pasan en la llamada a lockAndCall tenía la intención de representar un puntero nulo, pero lo que en realidad pasó fue int. Tratando de pasar de este int a la f1 como un std::shared_ptr<int> es un tipo de error. La llamada a lockAndCall con 0 falla debido a que dentro de la plantilla, un int se pasa a una función que requiere un std::shared_ptr<int>.

    El análisis de la llamada que implican NULL es esencialmente el mismo. Cuando NULL se pasa a lockAndCall, un tipo integral que se deduce para el parámetro ptr, y un tipo de error se produce cuando ptr—int o int-como el tipo se pasa a f2, en la que se espera obtener un std::unique_ptr<int>.

    En contraste, la llamada que implican nullptr no tiene ningún problema. Cuando nullptr se pasa a lockAndCall, el tipo de ptr se deduce a ser std::nullptr_t. Cuando ptr se pasa a f3, hay una conversión implícita de std::nullptr_t a int*, porque std::nullptr_t se convierte implícitamente a todos los tipos de puntero.

    Se recomienda, Siempre que desea hacer referencia a un puntero nulo, uso nullptr, no 0 o NULL.

  5. 4

    No hay ninguna ventaja directa de tener nullptr en la forma que se muestra en los ejemplos.

    Pero considere una situación en la que tiene 2 funciones con el mismo nombre; 1 toma int y otro un int*

    void foo(int);
    void foo(int*);

    Si quieres llamar la foo(int*) por el paso de una NULO, entonces el camino es:

    foo((int*)0); //note: foo(NULL) means foo(0)

    nullptr hace más fácil e intuitiva:

    foo(nullptr);

    Enlace adicional de Bjarne de la página web.

    Irrelevante, pero en C++11 nota:

    auto p = 0; //makes auto as int
    auto p = nullptr; //makes auto as decltype(nullptr)
    • Para referencia, decltype(nullptr) es std::nullptr_t.
    • Es std::nullptr_t un typedef, #define o algo?
    • Es un completo soplado tipo como yo sé.
    • Y así, es un (verdadero) tipo de puntero? Y si es así, ¿qué tipo de punto a? (Yo soy muy curioso. En serio.)
    • Es una pregunta interesante. cppreference tiene: typedef decltype(nullptr) nullptr_t;. Supongo que puedo mirar en el estándar. Ah, se encontró que: Nota: std::nullptr_t es un tipo distinto que no es ni un tipo de puntero ni un puntero a tipo de miembro; por el contrario, un prvalue de este tipo es un puntero null constante, y puede ser convertida a un valor de puntero nulo o nulo miembro valor de puntero.
    • Oh. Ellos realmente les gusta siempre tomar las cosas de manera diferente entonces. Aún así, muchas gracias por el esfuerzo.
    • Es realmente una buena cosa que usted señaló la deducción de nullptr.
    • Esto es completamente incorrecto. Perfecto reenvío fue la verdadera motivación.
    • Había más de uno motivaciones. Muchas otras cosas útiles pueden ser descubiertas por los propios programadores en los próximos años. Así que usted no puede decir que no es un único y verdadero uso de nullptr.
    • Nunca me dijo que había un verdadero uso. Me dijo que no había una motivación, es decir, que 0 no puede reenviar para la mierda y nullptr puede.
    • Pero dijo que esta respuesta es «bastante incorrecta» simplemente porque no hablar de «la verdadera motivación» que hablaron en su respuesta. No sólo que esta respuesta (y la mía) ha recibido una downvote de usted.
    • Así, desde el reenvío es la principal motivación, entonces la respuesta no discutir es bastante incorrecto.
    • Que es más tonto. Una respuesta es incorrecta cuando se le da mal la información. Pero esta respuesta (así como la mía) no da ninguna información incorrecta.
    • Se sugiere que la motivación para nullptr era algo más que perfecta de reenvío, lo que no era.
    • La motivación NO era, obviamente, uno; no eran muchas. (Espera, déjame adivinar : ahora que van a decir «principal» de la motivación, a la derecha?)

  6. 4

    Así como otros ya han dicho, su principal ventaja radica en las sobrecargas. Y mientras explícita int vs puntero sobrecargas pueden ser raras, considere la posibilidad de la biblioteca estándar de funciones como std::fill (que ha mordido a mí más de una vez en C++03):

    MyClass *arr[4];
    std::fill_n(arr, 4, NULL);

    No se compila: Cannot convert int to MyClass*.

  7. 2

    De la OMI más importantes que los problemas de sobrecarga: en anidada plantilla de construcciones, es difícil no perder la pista de los tipos, y dando explícito de firmas es bastante empeño. Así que para todo lo que use, más precisamente enfocado a la finalidad, la mejor, se reducirá la necesidad explícita de firmas y permite que el compilador producir más perspicaz mensajes de error cuando algo va mal.

Dejar respuesta

Please enter your comment!
Please enter your name here