47

私はいくつかの既存のコードを「近代化」しようとしています。

  • 現在、メンバー変数「Device*device_」を持つクラスがあります。
  • newを使用して初期化コードでインスタンスを作成し、破棄に「deletedevice_」があります。
  • このクラスのメンバー関数は、Device*をパラメーターとして受け取る他の多くの関数を呼び出します。

これはうまく機能しますが、コードを「最新化」するには、として定義される変数を変更し、"std::unique_ptr<Device> device_"deleteの明示的な呼び出しを削除する必要があると考えました。これにより、コードがより安全になり、一般的に優れたものになります。

私の質問はこれです-

  • 次に、 device _変数をパラメーターとして必要とするすべての関数に渡すにはどうすればよいですか?

.getを呼び出して、各関数呼び出しで生のポインターを取得できます。しかし、それは醜いようで、そもそもunique_ptrを使用する理由のいくつかを無駄にします。

または、すべての関数を変更して、「Device *」タイプのパラメーターを取得する代わりに、「std :: unique_ptr&」タイプのパラメーターを取得するようにすることもできます。これは(私にとって)関数プロトタイプをやや曖昧にし、読みにくくします。

このためのベストプラクティスは何ですか?他のオプションを逃したことがありますか?

4

5 に答える 5

45

Modern C++ スタイルには、次の 2 つの重要な概念があります。

  • 所有
  • 無効

所有権とは、オブジェクト/リソース (この場合は のインスタンスDevice) の所有者に関するものです。いろいろstd::unique_ptrboost::scoped_ptrまたはstd::shared_ptr所有権についてです。

ただし、 nullityははるかに単純です。指定されたオブジェクトが null であるかどうかを表すだけであり、それ以外のことは気にせず、所有権についても気にしません!


クラスの実装を (一般的に) 方向に移動したのは正しかっunique_ptrたですが、目標が PIMPL を実装することである場合は、ディープ コピー セマンティクスを備えたスマート ポインターが必要になる場合があります。

これは、あなたのクラスがこのメモリの部分に対して唯一の責任を負い、そうでなければメモリがリークする可能性のあるさまざまな方法すべてをきちんと処理していることを明確に伝えています。


一方、リソースのほとんどのユーザーは、その所有権についてあまり気にすることができませんでした。

関数がオブジェクトへの参照を保持しない (マップなどに格納する) 限り、重要なのは、オブジェクトの有効期間が関数呼び出しの期間を超えていることだけです。

したがって、パラメータを渡す方法の選択は、可能なNullityによって異なります。

  • ヌルじゃない?参照を渡す
  • もしかしてヌル?pointer 、単純な裸のポインター、またはポインターのようなクラスを渡します (たとえば、null のトラップを使用)

于 2012-03-14T10:31:55.840 に答える
14

それは本当に依存します。関数が unique_ptr の所有権を取得する必要がある場合、その署名はunique_ptr<Device>bvを取得し、呼び出し元はstd::moveポインターを取得する必要があります。所有権が問題にならない場合は、生のポインター シグネチャを保持し、 を使用してポインター unique_ptr を渡しますget()。問題の関数が所有権を引き継がない場合、これは見苦しくありません。

于 2012-03-14T09:50:46.390 に答える
8

私は使用しますstd::unique_ptr const&。const 以外の参照を使用すると、呼び出された関数にポインターをリセットする可能性が与えられます。
これは、呼び出された関数がポインタのみを使用できることを表現する良い方法だと思います。
したがって、これにより、インターフェイスが読みやすくなります。渡されたポインターをいじる必要がないことはわかっています。

于 2012-03-14T09:47:07.453 に答える
2

std::unique_ptr状況にもよりますが、この場合はおそらく使用しないことをお勧めします。std::unique_ptr(通常、クラス内の動的に割り当てられたオブジェクトへの生のポインターを複数持つべきではありません。これも状況によって異なります。) 、 std::unique_ptr<> const&少し扱いに​​くく難読化されています)。これがオブジェクト内で動的に割り当てられた唯一のポインターである場合は、生のポインターとdeleteデストラクタをそのまま使用します。そのようなポインターが複数ある場合は、それぞれを別の基本クラスに格下げすることを検討します (ただし、生のポインターである可能性があります)。

于 2012-03-14T09:57:55.483 に答える
1

Device*それはあなたにとって実行可能ではないかもしれませんが、すべてのbyを置き換えることconst unique_ptr<Device>&は良い出発点です。

明らかに s をコピーすることはできずunique_ptr、移動したくありません。への参照で置き換えるunique_ptrと、既存の関数の本体の本体が機能し続けることができます。

トラップがあり、呼び出し先がorconst &を実行するのを防ぐために通過する必要があります。これでも変更可能なポインターがデバイスに渡されることに注意してください。このソリューションでは、へのポインターまたは参照を渡す簡単な方法がありません。unique_ptr.reset()unique_ptr().release()const Device

于 2012-03-14T09:49:52.833 に答える