std::static_pointer_cast, std::dynamic_pointer_cast, std::const_pointer_cast, std::reinterpret_pointer_cast
来自cppreference.com
< cpp | memory | shared ptr
定义于头文件 <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
返回空指针,则为它空。
令 Y
为 typename 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) 后, |
(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 (公开成员函数) |