名前空間
変種
操作

std::static_pointer_cast、std::dynamic_pointer_cast、std::const_pointer_cast、std::reinterpret_pointer_cast

From cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
メモリ管理ライブラリ
(説明用*)
未初期化メモリのアルゴリズム
(C++17)
(C++17)
(C++17)
制約付き未初期化
メモリアルゴリズム
Cライブラリ

アロケータ
メモリリソース
ガベージコレクションのサポート
(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++20まで*)
明示的な生存期間管理
 
 
ヘッダ <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以降)

r の格納されているポインタをキャスト式を使用して取得した、新しい std::shared_ptr のインスタンスを作成します。

r が空の場合、新しい shared_ptr も空になります(ただし、格納されているポインタが必ずしも null とは限りません)。それ以外の場合、新しい shared_ptr は r の初期値と所有権を共有しますが、dynamic_pointer_cast によって実行された dynamic_cast が null ポインタを返した場合、それは空になります。

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 の結果が null ポインタ値の場合、返される 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_cast が失敗した場合、dynamic_pointer_cast (4) では 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())) は同じ効果を持つように見えるかもしれませんが、これらはすべて、同じオブジェクトを二重に削除しようとする、未定義の動作につながる可能性が高いです。

[編集] 実装例

static_pointer_cast
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};
}
dynamic_pointer_cast
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>{};
}
const_pointer_cast
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};
}
reinterpret_pointer_cast
template<class T, class U>
std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U>& r) noexcept
{
    auto p = reinterpret_cast<typename std::shared_ptr<T>::element_type*>(r.get());
    return std::shared_ptr<T>{r, p};
}

[編集]

#include <iostream>
#include <memory>
 
class Base
{
public:
    int a;
    virtual void f() const { std::cout << "I am base!\n"; }
    virtual ~Base() {}
};
 
class Derived : public Base
{
public:
    void f() const override { std::cout << "I am derived!\n"; }
    ~Derived() {}
};
 
int main()
{
    auto basePtr = std::make_shared<Base>();
    std::cout << "Base pointer says: ";
    basePtr->f();
 
    auto derivedPtr = std::make_shared<Derived>();
    std::cout << "Derived pointer says: ";
    derivedPtr->f();
 
    // static_pointer_cast to go up class hierarchy
    basePtr = std::static_pointer_cast<Base>(derivedPtr);
    std::cout << "Base pointer to derived says: ";
    basePtr->f();
 
    // dynamic_pointer_cast to go down/across class hierarchy
    auto downcastedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
    if (downcastedPtr)
    {
        std::cout << "Downcasted pointer says: ";
        downcastedPtr->f();
    }
 
    // All pointers to derived share ownership
    std::cout << "Pointers to underlying derived: "
              << derivedPtr.use_count()
              << '\n';
}

出力

Base pointer says: I am base!
Derived pointer says: I am derived!
Base pointer to derived says: I am derived!
Downcasted pointer says: I am derived!
Pointers to underlying derived: 3

[編集] 関連項目

新しい shared_ptr を構築する
(public メンバ関数) [編集]
English 日本語 中文(简体) 中文(繁體)