OK, so first some things that might be relevant:
I\'m using the Clang 3.1 compiler, in C++11 mode, with the standard library set to libc++.
I\'m trying to fa
The observed behavior is in accordance with the standard.
For unique_ptr
, 20.7.1.2.2/2 (destructor effects) says
Effects: If
get() == nullptr
there are no effects. Otherwiseget_deleter()(get())
.
For shared_ptr
, 20.7.2.2.2/1 says that the deleter should be called even if it wraps the null pointer:
Effects:
- If *this is empty or shares ownership with another
shared_ptr
instance (use_count() > 1
), there are no side effects.- Otherwise, if *this owns an object
p
and a deleterd
,d(p)
is called.- Otherwise, *this owns a pointer
p
, anddelete p
is called.
The important detail here is the expression "owns an object p
". 20.7.2.2/1 says that "a shared_ptr
object is empty if it does not own a pointer". 20.7.2.2.1/9 (the relevant constructor) says that it "constructs a shared_ptr
object that owns the object p
and the deleter d
".
So as far as I can tell, that invocation technically makes the shared_ptr
own the null pointer, which results in the deleter being called. Contrast this with the parameterless constructor which is said to leave the shared_ptr
"empty".
Yes it is the correct behavior.
§20.7.1.2.2[unique.ptr.single.dtor]/2:
unique_ptr
destructorEffects: If
get() == nullptr
there are no effects. Otherwiseget_deleter()(get())
.
§20.7.2.2.2[util.smartptr.shared.dest]/1:
shared_ptr
destructorEffects:
- If
*this
is empty or shares ownership with anothershared_ptr
instance (use_count() > 1
), there are no side effects.- Otherwise, if
*this
owns an objectp
and a deleterd
,d(p)
is called.- Otherwise,
*this
owns a pointerp
, and deletep
is called.
So there should be no effect since the shared_ptr is empty? Wrong, because providing the a pointer makes the shared_ptr not empty, even if the pointer is null.
§20.7.2.2.1[util.smartptr.shared.const]/8–10
shared_ptr
constructorstemplate<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
Requires:
p
shall be convertible toT*
. …Effects: Constructs a
shared_ptr
object that owns the objectp
and the deleterd
.Postconditions:
use_count() == 1 && get() == p
.
This means the shared_ptr owns the nullptr. Thus the deleter will be called when the shared_ptr is destroyed.