Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shared_ptr aliasing constructor

Question about following shared_ptr constructor:

template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );

Am I correct that if r was created using user-provided deleter, then aliasing shared_ptr knows that. So if aliasing shared_ptr is last in the group and (when going out of scope) destructs resources originally managed by r, it will use that user-provided deleter?

like image 508
user2052436 Avatar asked Sep 30 '13 19:09

user2052436


1 Answers

Example:

#include <iostream>
#include <iomanip>

struct some_type
{
    int i;
};

void my_deleter(some_type* p)
{
std::cout << "my_deleter called!" << std::endl;
    delete p;
}

#include <memory>
int main()
{
    std::shared_ptr<int> pm;

    {
        // Note: better use make_shared
        auto x = new some_type;
        // create a shared_ptr that owns x and a deleter
        std::shared_ptr<some_type> r(x, &my_deleter);
        std::cout << r.use_count() << std::endl;

        // share ownership of x and the deleter with pm
        pm = std::shared_ptr<int>(r, &r->i);
        std::cout << r.use_count() << std::endl;

        // r gets destroyed
    }
    std::cout << pm.use_count() << std::endl;
    std::cout << "get_deleter == 0? " << std::boolalpha
              << (nullptr == std::get_deleter<decltype(&my_deleter)>(pm))
              << std::endl;
}

Output:

1
2
1
get_deleter == 0? false
my_deleter called!

N.B. I can't compile this example with a free function my_deleter, there's some casting error for the free get_deleter function (trying to cast from void* to a function pointer type with a static_cast).


Aliasing ctor: [util.smartptr.shared.const]/13-14

template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept;

13 Effects: Constructs a shared_ptr instance that stores p and shares ownership with r.

14 Postconditions: get() == p && use_count() == r.use_count()

Ctor with user-provided deleter: [util.smartptr.shared.const]/9

template shared_ptr(Y* p, D d);

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

Dtor: [util.smartptr.shared.dest]/1

~shared_ptr();

1 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.

Combining those (let's skip the assignment operators):

  • The shared_ptr instance r owns both the object and the deleter.
  • The aliasing ctor lets the new shared_ptr instance share ownership with r (i.e. for both, the object and the deleter).
  • When the dtor of this new instance is called (or an assignment operator),
    • If use_count > 1, no effects.
    • Else, this instance owns the object which r pointed to and the deleter (if any) and will either use this deleter (if it exists) or delete on the object pointed to.
like image 160
dyp Avatar answered Sep 23 '22 01:09

dyp