2016-07-08 8 views
1

私が更新しているPre C++ 11/14コードベースがあります。C++ 14個のスタックに共有ポインタが割り当てられました

コードは、例えば、ほとんどelusivelyスタック割り当てを使用して、周りの人のポインタを渡します。この場合、

{ 
    KlassX x; 
    KlassY y; 

    y.doThings(&x); //Holds the pointer to KlassX for later use 

    return mainLoop(); //Doesn't return until the program finishes 
} 

を、KlassYは* KlassXのためのメモリの割り当てについては何も知りません。この特定のアプリケーションでは安全ですが、KlassYが別の方法で使用された場合、shared_ptrを使用してポインタを保持しているポインタの割り当て解除を追跡しないため、「安全なコード」ではありません。

プログラムをヒープ割り当てに変更せずに、shared_ptrを使用するためにKlassYを実装したいと思います。スタック割り当て方式を使用しても安全な方法はありますか?KlassXにはshared_ptrを使用していますか?

重複している場合は申し訳ありませんが、私はかなりの量のグーグルを行い、この質問に対する回答を見つけることができませんでした。

+0

これは安全なコードではないという考えをあなたに与えたことはありますか? 'KlassY'が' KlassX'へのポインターの所有権の幻想を持たず、ヌルポインターセーフである限り、これは完全に安全なコードです。 –

+0

私が述べたように、この特定の使用状況では、安全です。しかし、私がいつかKlassYを拾い上げて全く別のプログラム環境に落としたいのであれば、それはもはや安全ではありません。 –

答えて

12

ここにshared_ptrを使用する理由はありません。あなたは所有権を共有していません! doThings()は、&xの所有権を取得していません(おそらくそれを行うことはできません)。生のポインタを観察することに何も問題はありません。

template <class T> 
using observer_ptr = T*; 
(実際 library funtamentals TS v2で実際のクラス型ですが、生のポインタの周りに基本的には非常に薄いラッパー)

をしていることを渡す:あなたはC++ 11のことをで強調したい場合は、単純に定義することができます代わりに。これは、概念的にも意味的にも未処理のポインタとは異なります。の所有権がないことをすべての当事者にさらに明確にしています。がここに入ります。ちょうど観察セマンティクス。

さらに、スタックオブジェクトの所有権はどういう意味ですか?

+0

将来的に私はKlassYを拾い上げ、それをまったく別の実装に落として、その状況を安全に処理できるようにしたいと考えています。私はあなたが私の意図を理解するために薄いラッパーを作るという考えが好きです。ありがとうございました。 –

+0

一意のポインタの使用。スタックに一意のポインタベクトルを割り当てたい場合はどうすればいいですか?スマートポインタがメモリ管理に使用されるため、これは意味をなさないと言われています。代わりにポインタのセットまたは固有のベクトルを使用する必要がありますか? – dylan

-1

ほとんど何が

#include <memory> 

template<typename T> 
struct NonDeleter { 
    void operator()(T* t) {} 
}; 

struct KlassX {}; 

class KlassY { 
    std::shared_ptr<KlassX> klassx_; 
public: 
    KlassY() : klassx_(nullptr) {} 
    void doThings(std::shared_ptr<KlassX> klassX) { 
     klassx_ = klassX; 
    } 
}; 

int mainLoop() { return 0; } 

int main() { 
    KlassX x; 
    KlassY y; 

    std::shared_ptr<KlassX> xptr(&x, NonDeleter<KlassX>()); 
    y.doThings(xptr); 

    return mainLoop(); 
} 

http://ideone.com/BXkYYq

ではなく、すべてが望ましい可能です。 shared_ptrの目的は所有権を伝えることであり、ここではその意味を逸らしています。さらに、フードの下では、共用データブロックを動的に割り当てるためにshared_ptrをフードの下で実装することができる。

もちろん、この共有ポインタを渡すたびに、参照カウントを加算したり減算したりするコストをアプリケーションに負担します。これを行うために、しかし、正当化のわずかな供給源であるかもしれない

は:

KlassX x; 
KlassY y; 

std::shared_ptr<KlassX> xptr(&x, NonDeleter<KlassX>()); 
y.doThings(xptr); 

int r = mainLoop(); 

// make sure we didn't leak references 
assert(xptr.use_count() == 1); 

return r; 

私は、この正当化はしかし、かなり希薄であると思います。

リファレンスカウントのチェッカーを予定しておらず、今後の機能で共有ダイナミックアロケート処理をサポートしたい場合は、未処理のポインタを使用するか、C++ 17の提案するobserver ptrの概念非所有を示します。 [可能な実装についてはproposalを参照してください]

-1

KlassY::doThingsstd::shared_ptrを受け入れるように設計することができます。
次に、あなたが実際にあなたのコード例で共有ポインタを必要としないという事実を回避するために(詳細はhereを参照)std::shared_ptrエイリアシングコンストラクタを使用することができます。ここで

は、私が何を意味するかの例です:

#include<memory> 
#include<iostream> 

void f(std::shared_ptr<int> ptr) { 
    std::cout << *ptr << std::endl; 
} 

int main() { 
    int x = 42; 
    std::shared_ptr<int> fake{}; 
    std::shared_ptr<int> ptr{fake, &x}; 
    f(ptr); 
} 

限り、あなたはxの寿命がyの1に少なくとも等しいことを確実にすることができるよう、あなたは問題ありません。

intのスペースを割り当てずに、割り当てられたスタックを渡しているということは、あなたが求めていたことであり、必要に応じて新しいアーキテクチャに向かってスムーズに移行できることに注意してください。

+1

私は、壊れたインタフェースを回避するために、エイリアシングコンストラクタを使用することでやや上手くいます。しかし意図的に壊れたインターフェイスを設計していますか? –

+0

@ T.C。あなたはOPで働いて、本当の問題が何かを知っていますか?私はそうではないので、私は彼を助けることができるものを理解しようとしており、私はその質問に真実をとどめようとしました。彼はそのようなインターフェースを求めています、それは行く方法です。彼がやっていることに私は同意していない。 – skypjack

関連する問題