12

*生のポインターを使用するとスレッド セーフではない可能性があり、設計の意図 (オプションの値、所有権など) が明確ではないため、できればすべての生のポインターをコードから削除します。ただし、ポインターを使用しないのはそれほど簡単ではない場合もあります。たとえば、多相型のコンテナー内の基本型にポインターを使用する傾向があります。

class A : noncopyable { ... };
class B : public A { ... };

std::vector<A*> v;
v.emplace_back(new B);

// temporary container for some operation
std::vector<A*> selected;
if(check())
   selected.emplace_back(v.front());

上記のコードについて何が言えますか? 所有者は誰ですか?それは共有所有権ですか?それが、おそらく次の場合に行うべき理由ですv

std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());

がオブジェクトを所有していることは明らかですが、生のポインターがあり、デザインが直感的でなくなるのはvまだ好きではありません。selected標準C++ライブラリを見ると、仕事をすることができるタイプは1つだけだと思います - std::reference_wrapper :

std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());

// temporary container for some operation
std::vector<std::reference_wrapper<A>> selected;
if(check())
  selected.emplace_back(*v.front());

そのコードについてどう思いますか?それは良い習慣ですか?std::ref()主にテンプレートを使用することを意図していることはわかってstd::crefいますが、ここではそれを使用して、デザインの意図を明確に示すこともできるようです。私が目にする唯一の問題は、 を逆参照std::reference_wrapperする必要get()があり、. 似たようなものを自分で書くべきですか?それとも、将来の C++ バージョンでそのようなユースケースのために reference_wrapper を拡張できるのでしょうか? フィードバックをお寄せください。operator*()operator->()unique_ptr

編集:コードサンプルを変更して、意図をよりよく示すようにしました。

4

2 に答える 2

6

あなたはすでに健全に見える解決策を提供しました。「どう思いますか?」という質問は理解しています。

私の個人的な感覚では、一方では安全性と明確性、他方ではコードの単純さとの間にある程度のバランスが存在する必要があります。あなたのソリューションは、安全性を重視しすぎて、シンプルさを損ないすぎているようです。「弱い参照」を保持するコンテナーを使用するときはいつでも、これらを表すために生のポインターを使用しました。確かに、これによりオブジェクトの所有者が誰であるかがはっきりしなくなる可能性がありますが、いくつかの利点もあります。「reference_wrapper」が何であるかを調べる必要がなく、コードが明確です。それら (弱参照のコンテナー) を一時的にのみ使用し、この使用法をカプセル化する場合、所有権の問題は最小限に抑える必要があります。

ただ、これは個人の好みの問題だと思います。同じ目的で異なるタイプを使用することを提案させてください。これは、Boost を使用する余裕がある場合に提供されます。「強い」参照 (リソースを所有する) には、Steve Watanabe のType Erasureライブラリを使用できます。フリーストアメモリを明示的に使用する必要はありません。また、小さな型の場合、ヒープメモリを完全に使用することから逃れることができると思います (小さなバッファの最適化を使用)。最近ブーストに採用されましたが、まだリリースされていないと思います。

弱い参照については、Boost.Optional で「オプションの参照」を使用することを検討してください。

int i = 0;
boost::optional<int&> oi = i; // note: int&
i = 2;
assert(*oi == 2);

これは、reference_wrapper と同じセマンティクスを持っています。

于 2012-12-14T09:36:55.613 に答える
1

shared_ptrそれらを'sと呼ぶことは論理的に間違っていないと思います。ただし、std :: weak_ptrの定義を見てください:

std :: weak_ptrは、std :: shared_ptrによって管理されるオブジェクトへの非所有(「弱い」)参照を保持するスマートポインターです。参照されるオブジェクトにアクセスするには、std::shared_ptrに変換する必要があります。

それはより良い候補かもしれません。少なくとも、ポインタをいじっているときは、selected一時的な所有権を引き継ぐ必要があります。元のポインタは共有ポインタに格納されるため、弱いポインタを使用する方が安全です。

于 2012-12-14T08:21:06.977 に答える