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.
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.
Related Topics¶
- C++ Pure Virtual Functions and Abstract Classes | C++那些事
- C++ assert | C++那些事
- C++ Bit Fields | C++那些事
- Implementing C++ Polymorphism in C | C++那些事
- C++ const Constants and Qualifiers | C++那些事
- The Complete C++ const Family | C++那些事
- C++ Dereference Operator * | C++那些事
- Ways to Return Multiple Values in C++ | C++那些事
- C++ mutable Keyword | C++那些事
- C++ restrict and Compiler Optimization | C++那些事