web-dev-qa-db-ja.com

所有権セマンティクスのような生のポインタに対してunique_ptrを返すのは悪い習慣ですか?

別のデータオブジェクトから作成された新しいFoobarオブジェクトを返す静的ファクトリメソッドを記述しました。私は最近、所有権のセマンティクスに取りつかれており、このファクトリメソッドが_unique_ptr_を返すことによって正しいメッセージを伝えているのかどうか疑問に思っています。

_class Foobar {
public:
    static unique_ptr<Foobar> factory(DataObject data);
}
_

私の意図は、クライアントコードにポインターを所有していることを伝えることです。スマートポインターがなければ、単に_Foobar*_を返します。ただし、潜在的なバグを回避するためにこのメモリを強制的に削除したいので、_unique_ptr_は適切なソリューションのように思えました。クライアントがポインターの有効期間を延長する場合、_unique_ptr_を取得したら、.release()を呼び出すだけです。

_Foobar* myFoo = Foobar::factory(data).release();
_

私の質問は2つの部分に分かれています。

  1. このアプローチは正しい所有権セマンティクスを伝えていますか?
  2. これは、生のポインタの代わりに_unique_ptr_を返す「悪い習慣」ですか?
49
Bret Kuhns

ファクトリメソッドからstd::unique_ptrを返すのは問題なく、推奨される方法です。それが伝えるメッセージは(IMO):あなたは今このオブジェクトの唯一の所有者です。さらに、あなたの便宜のために、オブジェクトはそれ自身を破壊する方法を知っています。

これは、生のポインターを返すよりもずっと良いと思います(クライアントは、このポインターをどのように、どのように破棄するかを覚えている必要があります)。

ただし、ポインタを解放してその有効期間を延長することについてのあなたのコメントは理解できません。一般的に、ポインターは常に何らかのRAII構造によって管理されるべきだと思うので、スマートポインターでreleaseを呼び出す理由はほとんどありません(releaseを呼び出すのは、追加のクリーンアップを保証するために何かを行った後、別の管理データ構造にポインターを置きます。たとえば、別の削除機能を持つunique_ptrなどです。

したがって、クライアントは、オブジェクト(またはポインターの複数のコピーが必要な場合はunique_ptr)を必要とする限り、unique_ptrを(返されたものから構築された別のshared_ptrなどの)どこかに単純に格納できます(そしてすべきです) 。したがって、クライアントサイドのコードは次のようになります。

std::unique_ptr<FooBar> myFoo = Foobar::factory(data);
//or:
std::shared_ptr<FooBar> myFoo = Foobar::factory(data);

個人的には、返されたポインター型(この場合はstd::unique_ptr<Foobar>)と使用済みの削除(この場合はstd :: default_deleter)のtypedefをファクトリオブジェクトに追加します。後でポインターの割り当てを変更することを決定した場合(したがって、std::unique_ptrの2番目のテンプレートパラメーターとして表示されるポインターの破棄に別のメソッドが必要な場合)に簡単になります。だから私はこのようなことをします:

class Foobar {
public:  
    typedef std::default_deleter<Foobar>     deleter;
    typedef std::unique_ptr<Foobar, deleter> unique_ptr;

    static unique_ptr factory(DataObject data);
}

Foobar::unique_ptr myFoo = Foobar::factory(data);
//or:
std::shared_ptr<Foobar> myFoo = Foobar::factory(data);
60
Grizzly

std::unique_ptrは、それが指すオブジェクトを一意に所有します。 「私はこのオブジェクトを所有していますが、他の誰も所有していません。」と書かれています。

それはまさにあなたが表現しようとしていることです:あなたは「この関数の呼び出し元:あなたは今このオブジェクトの唯一の所有者です。好きなようにしてください。その寿命はあなたの責任です」と言っています。

17
James McNellis

これは正確なセマンティクスを正確に伝えており、C++のすべてのファクトリが機能するはずだと思う方法です:std::unique_ptr<T>は、いかなる種類の所有権セマンティクスも課さないため、非常に安価です。

6
Dietmar Kühl