What exactly is nullptr?

前端 未结 14 2371
无人及你
无人及你 2020-11-22 01:12

We now have C++11 with many new features. An interesting and confusing one (at least for me) is the new nullptr.

Well, no need anymore for the nasty mac

相关标签:
14条回答
  • 2020-11-22 01:22

    nullptr can't be assigned to an integral type such as an int but only a pointer type; either a built-in pointer type such as int *ptr or a smart pointer such as std::shared_ptr<T>

    I believe this is an important distinction because NULL can still be assigned to both an integral type and a pointer as NULL is a macro expanded to 0 which can serve as both an initial value for an int as well as a pointer.

    0 讨论(0)
  • 2020-11-22 01:25

    Let's say that you have a function (f) which is overloaded to take both int and char*. Before C++ 11, If you wanted to call it with a null pointer, and you used NULL (i.e. the value 0), then you would call the one overloaded for int:

    void f(int);
    void f(char*);
    
    void g() 
    {
      f(0); // Calls f(int).
      f(NULL); // Equals to f(0). Calls f(int).
    }
    

    This is probably not what you wanted. C++11 solves this with nullptr; Now you can write the following:

    void g()
    {
      f(nullptr); //calls f(char*)
    }
    
    0 讨论(0)
  • 2020-11-22 01:27

    How is it a keyword and an instance of a type?

    This isn't surprising. Both true and false are keywords and as literals they have a type ( bool ). nullptr is a pointer literal of type std::nullptr_t, and it's a prvalue (you cannot take the address of it using &).

    • 4.10 about pointer conversion says that a prvalue of type std::nullptr_t is a null pointer constant, and that an integral null pointer constant can be converted to std::nullptr_t. The opposite direction is not allowed. This allows overloading a function for both pointers and integers, and passing nullptr to select the pointer version. Passing NULL or 0 would confusingly select the int version.

    • A cast of nullptr_t to an integral type needs a reinterpret_cast, and has the same semantics as a cast of (void*)0 to an integral type (mapping implementation defined). A reinterpret_cast cannot convert nullptr_t to any pointer type. Rely on the implicit conversion if possible or use static_cast.

    • The Standard requires that sizeof(nullptr_t) be sizeof(void*).

    0 讨论(0)
  • 2020-11-22 01:30

    Well, other languages have reserved words that are instances of types. Python, for instance:

    >>> None = 5
      File "<stdin>", line 1
    SyntaxError: assignment to None
    >>> type(None)
    <type 'NoneType'>
    

    This is actually a fairly close comparison because None is typically used for something that hasn't been intialized, but at the same time comparisons such as None == 0 are false.

    On the other hand, in plain C, NULL == 0 would return true IIRC because NULL is just a macro returning 0, which is always an invalid address (AFAIK).

    0 讨论(0)
  • 2020-11-22 01:30

    Here's the LLVM header.

    // -*- C++ -*-
    //===--------------------------- __nullptr --------------------------------===//
    //
    // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
    // See https://llvm.org/LICENSE.txt for license information.
    // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
    //
    //===----------------------------------------------------------------------===//
    
    #ifndef _LIBCPP_NULLPTR
    #define _LIBCPP_NULLPTR
    
    #include <__config>
    
    #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    #pragma GCC system_header
    #endif
    
    #ifdef _LIBCPP_HAS_NO_NULLPTR
    
    _LIBCPP_BEGIN_NAMESPACE_STD
    
    struct _LIBCPP_TEMPLATE_VIS nullptr_t
    {
        void* __lx;
    
        struct __nat {int __for_bool_;};
    
        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
    
        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
    
        template <class _Tp>
            _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
            operator _Tp* () const {return 0;}
    
        template <class _Tp, class _Up>
            _LIBCPP_INLINE_VISIBILITY
            operator _Tp _Up::* () const {return 0;}
    
        friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
        friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
    };
    
    inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}
    
    #define nullptr _VSTD::__get_nullptr_t()
    
    _LIBCPP_END_NAMESPACE_STD
    
    #else  // _LIBCPP_HAS_NO_NULLPTR
    
    namespace std
    {
        typedef decltype(nullptr) nullptr_t;
    }
    
    #endif  // _LIBCPP_HAS_NO_NULLPTR
    
    #endif  // _LIBCPP_NULLPTR
    

    (a great deal can be uncovered with a quick grep -r /usr/include/*`)

    One thing that jumps out is the operator * overload (returning 0 is a lot friendlier than segfaulting...). Another thing is it doesn't look compatible with storing an address at all. Which, compared to how it goes slinging void*'s and passing NULL results to normal pointers as sentinel values, would obviously reduce the "never forget, it might be a bomb" factor.

    0 讨论(0)
  • 2020-11-22 01:31

    From nullptr: A Type-safe and Clear-Cut Null Pointer:

    The new C++09 nullptr keyword designates an rvalue constant that serves as a universal null pointer literal, replacing the buggy and weakly-typed literal 0 and the infamous NULL macro. nullptr thus puts an end to more than 30 years of embarrassment, ambiguity, and bugs. The following sections present the nullptr facility and show how it can remedy the ailments of NULL and 0.

    Other references:

    • WikiBooks, with sample code.
    • Here at Stack Overflow: Do you use NULL or 0 (zero) for pointers in C++?
    • template
    • Google group: comp.lang.c++.moderated - compiler discussion
    0 讨论(0)
提交回复
热议问题