Does the standard behavior for deleters differ between shared_ptr and unique_ptr in the case of null pointers?

前端 未结 2 902
死守一世寂寞
死守一世寂寞 2021-01-01 09:59

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

相关标签:
2条回答
  • 2021-01-01 10:27

    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. Otherwise get_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 deleter d, d(p) is called.
    • Otherwise, *this owns a pointer p, and delete 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".

    0 讨论(0)
  • 2021-01-01 10:31

    Yes it is the correct behavior.

    §20.7.1.2.2[unique.ptr.single.dtor]/2:

    unique_ptr destructor

    Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

    §20.7.2.2.2[util.smartptr.shared.dest]/1:

    shared_ptr destructor

    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 deleter d, d(p) is called.
    • Otherwise, *this owns a pointer p, and delete p 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 constructors

    template<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 to T*. …

    Effects: Constructs a shared_ptr object that owns the object p and the deleter d.

    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.

    0 讨论(0)
提交回复
热议问题