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


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

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

    1. std::static_pointer_cast,
    2. std::dynamic_pointer_cast,
    3. std::const_pointer_cast,
    4. 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())) 看起来可能拥有相同效果,但它们全都很可能导致未定义行为,试图删除同一对象二次!

     

    可能的实现

    版本一

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

    版本二

    1. template< class T, class U >
    2. std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    3. {
    4. if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get())) {
    5. return std::shared_ptr<T>(r, p);
    6. } else {
    7. return std::shared_ptr<T>();
    8. }
    9. }

    版本三

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

    调用示例

    1. #include <iostream>
    2. #include <memory>
    3. struct BaseClass {};
    4. struct DerivedClass : BaseClass
    5. {
    6. void f() const
    7. {
    8. std::cout << "Hello World!\n";
    9. }
    10. ~DerivedClass() // 注意:它不是虚的
    11. {
    12. std::cout << "~DerivedClass\n";
    13. }
    14. };
    15. int main()
    16. {
    17. std::shared_ptr<BaseClass> ptr_to_base(std::make_shared<DerivedClass>());
    18. // ptr_to_base->f(); // 错误不会编译: BaseClass 无名为 'f' 的成员
    19. std::static_pointer_cast<DerivedClass>(ptr_to_base)->f(); // OK
    20. // (构造临时 shared_ptr ,然后调用 operator->
    21. static_cast<DerivedClass*>(ptr_to_base.get())->f(); // 亦 OK
    22. // (直接转型,不构造临时 shared_ptr )
    23. }

    输出

    访问 p 的删除器 

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

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

    参数

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

    返回值

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

    注意

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

    调用示例

    1. #include <iostream>
    2. #include <memory>
    3. struct Foo
    4. {
    5. int i;
    6. };
    7. void foo_deleter(Foo * p)
    8. {
    9. std::cout << "foo_deleter called!\n";
    10. delete p;
    11. }
    12. int main()
    13. {
    14. std::shared_ptr<int> aptr;
    15. {
    16. // 创建拥有一个 Foo 和删除器的 shared_ptr
    17. auto foo_p = new Foo;
    18. std::shared_ptr<Foo> r(foo_p, foo_deleter);
    19. aptr = std::shared_ptr<int>(r, &r->i); // 别名使用构造函数
    20. // aptr 现在指向 int ,但管理整个 Foo
    21. } // r 被销毁(不调用删除器)
    22. // 获得指向删除器的指针:
    23. if (auto del_p = std::get_deleter<void(*)(Foo*)>(aptr))
    24. {
    25. std::cout << "shared_ptr owns a deleter\n";
    26. if (*del_p == foo_deleter)
    27. {
    28. std::cout << "...and it equals &foo_deleter\n";
    29. }
    30. }
    31. else
    32. {
    33. std::cout << "The deleter of shared_ptr is null!\n";
    34. }
    35. } // 于此调用删除器

    输出

     

  • 相关阅读:
    2023年第十四届蓝桥杯大赛软件类省赛C/C++大学A组真题
    Linux文件打包及压缩、解包及解压
    线上mysql表字段加不了Fail to get MDL on replica during DDL synchronize,排查记录
    ONP: Error #15: Initializing libiomp5md.dll【报错系列】
    webpack优化系列三:vue子目录路径更改---publicPath
    4.求1000以内的所有完数
    【多卡训练报错】:The server socket has failed to listen on any local network address.
    java基于ssm+vue的婚纱摄影网站
    正则表达式使用文档
    竞赛 深度学习驾驶行为状态检测系统(疲劳 抽烟 喝水 玩手机) - opencv python
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/126790780