9

关于以下shared_ptr构造函数的问题:

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

我是否正确,如果r是使用用户提供的删除器创建的,那么别名就shared_ptr知道了。因此,如果别名shared_ptr是组中的最后一个并且(超出范围时)破坏了最初由 管理的资源r,它将使用用户提供的删除器吗?

4

2 回答 2

5

例子:

#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;
}

输出:

1
2
1
get_deleter == 0?错误的
my_deleter 调用!

注意我不能用自由函数编译这个例子,自由函数my_deleter有一些转换错误get_deleter(试图void*用 a 转换为函数指针类型static_cast)。


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

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

13效果:构造一个实例来shared_ptr存储p共享所有权r

14后置条件: get() == p && use_count() == r.use_count()

带有用户提供的删除器的 ctor:[util.smartptr.shared.const]/9

模板 shared_ptr(Y* p, D d);

效果:构造一个拥有该对象shared_ptr和删除器的对象。pd

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

~shared_ptr();

1效果:

  • 如果*thisshared_ptr或与另一个实例共享所有权( use_count() > 1),则没有副作用。
  • 否则,如果*this 拥有一个对象p和一个删除器dd(p)则调用。
  • 否则,*this 拥有一个指针p,并被delete p调用。

结合这些(让我们跳过赋值运算符):

  • shared_ptr实例同时r 拥有对象和删除器。
  • 别名 ctor 让新shared_ptr实例与(即对象和删除器)共享所有权。r
  • 当这个新实例的 dtor 被调用(或赋值运算符)时,
    • 如果use_count > 1,则没有影响。
    • 否则,此实例拥有r指向的对象删除器(如果有),并将使用此删除器(如果存在)或delete指向的对象。
于 2013-09-30T19:36:03.783 回答
0

是的,因为删除器存储在 shared_ptr 的计数器(“pn”成员boost::detail::shared_count)中,并且别名实际上共享该计数器。

于 2016-01-18T11:43:09.387 回答