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

来自cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
工具库
通用工具
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)

初等字符串转换
(C++17)
(C++17)
栈踪
 
动态内存管理
智能指针
(C++11)
(C++11)
(C++11)
(C++17 前)
(C++11)
(C++23)
分配器
内存资源
未初始化存储
未初始化内存算法
受约束的未初始化内存算法
垃圾收集支持
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
杂项
(C++20)
(C++11)
(C++11)
C 库
低层内存管理
 
 
定义于头文件 <memory>
template< class T, class U >
std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept;
(1) (C++11 起)
template< class T, class U >
std::shared_ptr<T> static_pointer_cast( std::shared_ptr<U>&& r ) noexcept;
(2) (C++20 起)
template< class T, class U >
std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept;
(3) (C++11 起)
template< class T, class U >
std::shared_ptr<T> dynamic_pointer_cast( std::shared_ptr<U>&& r ) noexcept;
(4) (C++20 起)
template< class T, class U >
std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept;
(5) (C++11 起)
template< class T, class U >
std::shared_ptr<T> const_pointer_cast( std::shared_ptr<U>&& r ) noexcept;
(6) (C++20 起)
template< class T, class U >
std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept;
(7) (C++17 起)
template< class T, class U >
std::shared_ptr<T> reinterpret_pointer_cast( std::shared_ptr<U>&& r ) noexcept;
(8) (C++20 起)

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

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

Ytypename std::shared_ptr<T>::element_type ,则将分别通过求值下列表达式,获得生成 std::shared_ptr 的存储指针:

1-2) static_cast<Y*>(r.get())
3-4) dynamic_cast<Y*>(r.get()) (若 dynamic_cast 的结果是空指针值,则返回的 shared_ptr 将为空)。
5-6) const_cast<Y*>(r.get())
7-8) reinterpret_cast<Y*>(r.get())

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

1-2) 行为未定义,除非 static_cast<T*>((U*)nullptr) 为良式。
3-4) 行为未定义,除非 dynamic_cast<T*>((U*)nullptr) 为良式。
5-6) 行为未定义,除非 const_cast<T*>((U*)nullptr) 为良式。
7-8) 行为未定义,除非 reinterpret_cast<T*>((U*)nullptr) 为良式。

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

(C++20 起)

参数

r - 要转换的指针

注意

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

可能的实现

版本一
template< class T, class U > 
std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
    auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>(r, p);
}
版本二
template< class T, class U > 
std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
    if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get())) {
        return std::shared_ptr<T>(r, p);
    } else {
        return std::shared_ptr<T>();
    }
}
版本三
template< class T, class U > 
std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
    auto p = const_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>(r, p);
}

示例

#include <iostream>
#include <memory>
 
struct BaseClass {};
 
struct DerivedClass : BaseClass
{
    void f() const
    {
        std::cout << "Hello World!\n";
    }
    ~DerivedClass(){ // 注意:它不是虚的
        std::cout << "~DerivedClass\n";
    }
};
 
int main()
{
    std::shared_ptr<BaseClass> ptr_to_base(std::make_shared<DerivedClass>());
 
    // ptr_to_base->f(); // 错误不会编译: BaseClass 无名为 'f' 的成员
 
    std::static_pointer_cast<DerivedClass>(ptr_to_base)->f(); // OK
    // (构造临时 shared_ptr ,然后调用 operator-> )
 
    static_cast<DerivedClass*>(ptr_to_base.get())->f(); // 亦 OK
    // (直接转型,不构造临时 shared_ptr )
}

输出:

Hello World!
Hello World!
~DerivedClass

参阅

构造新的 shared_ptr
(公开成员函数)