Skip to content

Last updated:2026-10-12

C++ Initialization and Assignment

C++ iv

int* p = nullptr;
std::shared_ptr<int> s(p); // 计数器1
std::shared_ptr<int> s2(s); // 计数器2
assert(s.use_count() == 2); 

This piece of code raises several questions:

  • Why is the use count of the smart pointer constructed from a nullptr raw pointer not 0?
  • Is delete nullptr safe?

1. The Semantics of an Empty shared_ptr

Looking directly at the shared_ptr source code, what "empty" means is:

  • A shared_ptr constructed by default construction
  • A shared_ptr constructed from nullptr_t

Only these two cases count as empty; a shared_ptr constructed from a raw pointer owns that pointer, regardless of whether it is null.

They correspond to the three constructors below.

private:
    element_type*      __ptr_;
    __shared_weak_count* __cntrl_;

public:
    _LIBCPP_HIDE_FROM_ABI
    _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT
        : __ptr_(nullptr),
          __cntrl_(nullptr)
    { }

    _LIBCPP_HIDE_FROM_ABI
    _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT
        : __ptr_(nullptr),
          __cntrl_(nullptr)
    { }
    shared_ptr(_Yp* __p, _Dp __d)
        : __ptr_(__p)
    {}

In the case above, where the raw pointer is nullptr, what happens on delete nullptr? And what happens if you delete twice?

2. delete nullptr

Given the following code, does it crash when run, or run normally?

#include <iostream>

int main() {
    int *p = nullptr;
    delete p;
    std::cout << "delete once" << std::endl;
    delete p;
    std::cout << "delete twice" << std::endl;

}

The answer is: it prints normally.

See cppreference for the specific reason:

If expression evaluates to a null pointer value, no destructors are called, and the deallocation function may or may not be called (it's unspecified), but the default deallocation functions are guaranteed to do nothing when passed a null pointer.

https://en.cppreference.com/w/cpp/language/delete

If the expression evaluates to a null pointer value, no destructors are called, and the deallocation function may or may not be called (unspecified), but the default deallocation functions are guaranteed to do nothing when passed a null pointer.

Reading tips

This article discusses the difference between initialization and assignment in C++; see also the class initializer list.

Comments