2016-10-31 14 views
0

を最適化するために、次の2つのクラスAnimalDogを(AnimalからどこDog継承)持っている、とあなたは、多くの場合、動物を期待しているが、犬のインスタンスを送信している状況があります。私の場合、私はしばしば、動物の期待機能(std::shared_ptr<Animal>)に強いポインタ(std::shared_ptr<Dog>)を投げかけています。C++ reinterpret_castは:: shared_ptrの参照

関数のパラメータを参照(std::shared_ptr<Animal>&、スレッドで所有権を変更することの懸念から参照パラメータとして強力なポインタを持たないべき理由を避けるため)をすることができると受け入れる場合、私は安全なメモリ「reinterpret_cast<std::shared_ptr<Animal>&>(dog)」を使用してstd::shared_ptr<Dog> dogをキャストすると

もしそうなら、スレッドの問題以外に何が起こる可能性がありますか。参照カウントの種類のようなものですか?

明確にするために、一度キャスティングすることは実際に実行可能な解決策ではない多くの場合に使用される解決策を用意することです。キャストする必要がある多くのオブジェクトがあるということは、より多くの問題です。また、それを無視してstd::unique_ptrは良い解決策かもしれません。

最終的な要件を追加するには、プレーン・ポインタを使用すると、仮想化された一般化されたシリアライザ・クラス関数の場合にオリジナルのstd::shared_ptrをテンプレート化することができません。

+0

なぜ['static_pointer_cast'](http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)を使用しないのですか? – krzaq

+0

オーバーヘッドを避けるには。私の場合、これはコードが生成されている場所です。または、継承の複数のレイヤーを持ち、上向きにキャストする必要があるカスタムコピーコンストラクターを構築する場合。 –

+0

これらのクラスは継承によって関連していますか? – Steve

答えて

0

私はしばしば、動物の期待機能(std::shared_ptr<Animal>)に強いポインタ(std::shared_ptr<Dog>)を投げかけています。

(すなわち明示的変換)をキャストする必要はありません。派生型への共有ポインタは、暗黙的に基本クラスへの共有ポインタに変換可能です(1)。我々は我々が参照

関数のパラメータを作ることができることを受け入れる場合は、いくつかの要件が満たされている場合

(A)私たちは、この仮定を受け入れることができます。第1に、関数は、(コピーを除いて)関数のスコープを超えて参照される引数を格納してはならない。第2に、参照として渡されたポインタは、ローカルまたは一時的でなければなりません。そうでない場合、関数は参照されたポインタに直接的または間接的にアクセスできる関数を呼び出してはなりません。

また、リファレンスが非constの場合、暗黙的な変換(1)に依存することはできません。代わりに、正しい型の別の共有ポインタを作成する必要があります(暗黙の変換を使用してそれを作成して渡すことができます)。const参照引数または非参照引数はその問題を持ちません。

)私は右、私たちは安全なメモリワイズreinterpret_cast<std::shared_ptr<Animal>&>(dog)を使用してのstd :: shared_ptrの犬をキャストするだろうと仮定し

標準ワイズ、あなたの提案キャストは安全ではありません - ?。それは未定義の動作をしている私は表示されません仮定(b)が仮定(a)にどのように従うか。


それはあなたのケースでは、引数としてshared_ptrのための基準を使用して大丈夫ですが、あなたが原因(定数にベース、非constへの派生)の変換にrefcounterの増加/減少を避けることができない場合、私は使用をお勧めします代わりに引数のための裸のポインタ。

+0

通常のポインタを使用するだけで、私が持っているカスタムコピーコンストラクタのケースを処理する可能性があります。しかし、裸のポインタを使用する注意点は、私が実際にそれをしたい場合には、元の 'std :: shared_ptr'自体を変更できないということです。例えば、私は変数を変更する必要がある一般化された 'Serialize()'メソッドを持っていて、メソッド自体は仮想化する必要があるためテンプレート化できません。 –

+0

あなたはおそらく裸のポインタを渡し、派生型の共有ポインタを受け入れることができない関数が派生ポインタを返すことができないため、ダウンキャストの後に 'shared_ptr'に割り当てる裸のポインタを返すことができます。 – user2079303