c++11 智能指针 (std::shared_ptr)(五)

 定义于头文件 
template< class T > class shared_ptr;     (C++11 起) 

创建 std::shared_ptr 的新实例,其存储指针从 r 的存储指针用转型表达式获得。

std::static_pointer_cast, 
std::dynamic_pointer_cast, 
std::const_pointer_cast, 
std::reinterpret_pointer_cast

template< class T, class U >
std::shared_ptr static_pointer_cast( const std::shared_ptr& r ) noexcept;

(1) (C++11 起)

template< class T, class U >
std::shared_ptr static_pointer_cast( std::shared_ptr&& r ) noexcept;

(2) (C++20 起)

template< class T, class U >
std::shared_ptr dynamic_pointer_cast( const std::shared_ptr& r ) noexcept;

(3) (C++11 起)

template< class T, class U >
std::shared_ptr dynamic_pointer_cast( std::shared_ptr&& r ) noexcept;

(4) (C++20 起)

template< class T, class U >
std::shared_ptr const_pointer_cast( const std::shared_ptr& r ) noexcept;

(5) (C++11 起)

template< class T, class U >
std::shared_ptr const_pointer_cast( std::shared_ptr&& r ) noexcept;

(6) (C++20 起)

template< class T, class U >
std::shared_ptr reinterpret_pointer_cast( const std::shared_ptr& r ) noexcept;

(7) (C++17 起)

template< class T, class U >
std::shared_ptr reinterpret_pointer_cast( std::shared_ptr&& r ) noexcept;

(8) (C++20 起)

创建 std::shared_ptr 的新实例,其存储指针从 r 的存储指针用转型表达式获得。

r 为空,则新的 shared_ptr 亦然(但其存储指针不必为空)。否则,新的 shared_ptr 将与 r 的初始值共享所有权,除了若 dynamic_pointer_cast 所进行的 dynamic_cast 返回空指针,则为它空。

Y 为 typename std::shared_ptr::element_type ,则将分别通过求值下列表达式,获得生成 std::shared_ptr 的存储指针:

1-2) static_cast(r.get()) 。

3-4) dynamic_cast(r.get()) (若 dynamic_cast 的结果是空指针值,则返回的 shared_ptr 将为空)。

5-6) const_cast(r.get()) 。

7-8) reinterpret_cast(r.get()) 。

这些函数的行为未定义,除非从 U*T* 的对应转型为良式:

1-2) 行为未定义,除非 static_cast((U*)nullptr) 为良式。

3-4) 行为未定义,除非 dynamic_cast((U*)nullptr) 为良式。

5-6) 行为未定义,除非 const_cast((U*)nullptr) 为良式。

7-8) 行为未定义,除非 reinterpret_cast((U*)nullptr) 为良式。

调用右值重载 (2,4,6,8) 后, r 为空且 r.get() == nullptr ,除了对于 dynamic_pointer_cast (4) ,若 dynamic_cast 失败则不修改 r

(C++20 起)

参数

r - 要转换的指针

注意

表达式 std::shared_ptr(static_cast(r.get())) 、 std::shared_ptr(dynamic_cast(r.get())) 及 std::shared_ptr(const_cast(r.get())) 看起来可能拥有相同效果,但它们全都很可能导致未定义行为,试图删除同一对象二次!

 

可能的实现

版本一

template< class T, class U > 
std::shared_ptr static_pointer_cast( const std::shared_ptr& r ) noexcept
{
    auto p = static_cast::element_type*>(r.get());
    return std::shared_ptr(r, p);
}

版本二

template< class T, class U > 
std::shared_ptr dynamic_pointer_cast( const std::shared_ptr& r ) noexcept
{
    if (auto p = dynamic_cast::element_type*>(r.get())) {
        return std::shared_ptr(r, p);
    } else {
        return std::shared_ptr();
    }
}

版本三

template< class T, class U > 
std::shared_ptr const_pointer_cast( const std::shared_ptr& r ) noexcept
{
    auto p = const_cast::element_type*>(r.get());
    return std::shared_ptr(r, p);
}

调用示例

#include 
#include 

struct BaseClass {};

struct DerivedClass : BaseClass
{
    void f() const
    {
        std::cout << "Hello World!\n";
    }
    ~DerivedClass()  // 注意:它不是虚的
    {
        std::cout << "~DerivedClass\n";
    }
};

int main()
{
    std::shared_ptr ptr_to_base(std::make_shared());

//    ptr_to_base->f(); // 错误不会编译: BaseClass 无名为 'f' 的成员

    std::static_pointer_cast(ptr_to_base)->f(); // OK
    // (构造临时 shared_ptr ,然后调用 operator-> )

    static_cast(ptr_to_base.get())->f(); // 亦 OK
    // (直接转型,不构造临时 shared_ptr )
}

输出

c++11 智能指针 (std::shared_ptr)(五)_第1张图片

访问 p 的删除器 

std::get_deleter
template< class Deleter, class T >
Deleter* get_deleter( const std::shared_ptr& p ) noexcept;(C++11 起) 

访问 p 的删除器。若共享指针 p 占有无 cv 限定 Deleter 类型的删除器(例如,若它以接收删除器为参数的构造函数之一创建),则返回指向删除器的指针。否则,返回空指针。

参数

p - 需要访问其删除器的共享指针

返回值

指向被占有删除器的指针或 nullptr 。只要至少还有一个 shared_ptr 实例占有返回的指针,它就合法。

注意

返回的指针可能比最后一个 shared_ptr 的生存期更持久,例如,还剩下 std::weak_ptr 时且实现在销毁整个控制块前不销毁删除器。

调用示例

#include 
#include 

struct Foo
{
    int i;
};
void foo_deleter(Foo * p)
{
    std::cout << "foo_deleter called!\n";
    delete p;
}

int main()
{
    std::shared_ptr aptr;

    {
        // 创建拥有一个 Foo 和删除器的 shared_ptr
        auto foo_p = new Foo;
        std::shared_ptr r(foo_p, foo_deleter);
        aptr = std::shared_ptr(r, &r->i); // 别名使用构造函数
        // aptr 现在指向 int ,但管理整个 Foo
    } // r 被销毁(不调用删除器)

    // 获得指向删除器的指针:
    if (auto del_p = std::get_deleter(aptr))
    {
        std::cout << "shared_ptr owns a deleter\n";
        if (*del_p == foo_deleter)
        {
            std::cout << "...and it equals &foo_deleter\n";
        }
    }
    else
    {
        std::cout << "The deleter of shared_ptr is null!\n";
    }
} // 于此调用删除器

输出

c++11 智能指针 (std::shared_ptr)(五)_第2张图片

 

你可能感兴趣的:(#,智能指针,c++,智能指针,shared_ptr)