shared_ptr别名构造函数

shared_ptr aliasing constructor

本文关键字:构造函数 别名 ptr shared      更新时间:2023-10-16

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

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

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

示例:

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

输出:

121get_deleter == 0?假my_deleter打电话!

:注:我无法使用自由函数my_deleter编译此示例,自由get_deleter函数存在一些转换错误(尝试从void*转换为带有static_cast的函数指针类型(。


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

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

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

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

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

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

效果:构造一个shared_ptr对象,该对象拥有对象p和删除程序d

多托:[util.smartptr.shared.dest]/1

~shared_ptr((;

1 效果:

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

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

  • shared_ptr实例r同时拥有对象和删除程序。
  • 别名 ctor 允许新的 shared_ptr 实例与r共享所有权(即对象和删除器(。
  • 当调用此新实例的 dtor(或赋值运算符(时,
    • 如果use_count > 1,则没有效果。
    • 否则,此实例拥有r指向的对象删除程序(如果有(,并将使用此删除器(如果存在(或delete指向的对象。

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