8

私はC++11-いくつかのコードを使用しています。私は持っています

class X { /* */ };

class A {
    std::vector<X*> va_x;
};

class B {
    std::vector<X*> vb_x;
    std::vector<A> vb_a;
};

クラスA内の「va_x」のX*は、クラスB内の「vb_x」のX*によってもポイントされているオブジェクトを指します。

ここで、スマートポインタを使用したいと思います。私にとって、クラスBがX *によってポイントされるオブジェクトの所有権を持っていることは明らかです(特に私のAインスタンスはBに属しているため)

したがって、B内のXにunique_ptrを使用する必要があります。

class B {
    std::vector<unique_ptr<X>> vb_x;
    std::vector<A> vb_a;
};

私の質問は、クラスAに対して何をすべきかということです。生のポインタを保持する必要がありますか?そうすることで、私の単体テストでは、たとえば、厄介なこと(imo)につながることを認めなければなりません(カプセル化について心配する必要はありません。それは重要ではありません)。

unique_ptr<X> x(new X());
A a;
a.va_x.push_back(&(*x)); //awkward, but what else can I do?

A.vb_a.push_back(a); //ok
B.vb_x.push_back(move(x)); //ok
4

2 に答える 2

10

x.get()内部ポインタを返す、を使用できます。

それ以外は、はい、所有していない参照を処理するために生のポインターを使用するのが道です。この質問も参照してください。

于 2012-09-23T19:35:05.593 に答える
-1

Xeoが彼の答えで述べているように、解決策は一般的にを使用することx.get()です。

アクセスする必要があるときはいつでもFILEを使用する例があります。x.get()

void file_deleter(FILE *f)
{
    fclose(f);
}

[...]

{
    std::unique_ptr<FILE, decltype(&file_deleter)>
                       f(fopen("/tmp/test.tmp", "rw"), &file_deleter);

    // read/write use f.get() as in:
    fread(buf, 1, sizeof(buf), f.get());
    fwrite(buf, 1, sizeof(buf), f.get());

    // fclose() gets called in the deleter, no need to do anything
}

ただし、あなたの場合は、を使用する必要がありますx.release()

A a;
{
    unique_ptr<X> x(new X());
    a.va_x.push_back(&(*x)); // this is wrong
}
// here a[0] is a dangling pointer

&(*x)は生のポインタを取得し、ベクターにコピーを作成しますa。ただし、unique_ptr<>スコープ外になると、そのポインタは削除されます。したがって、の後に}、ベクトル内のポインタはa適切ではなくなります(ただし、しばらくは機能する可能性があります)。

ベアポインタを転送する正しい方法は、次のようにrelease()関数を使用することです。

    a.va_x.push_back(x.release()); // this works

その1行の後、ポインターはaベクトル内にのみ存在します。これは、呼び出し元がそのリソースの管理を担当するようになるという考えで、一意のポインターから解放されました。

重要な注意:push_back()()をスローする可能性がbad_allocあり、その場合、リソースは失われます。この問題を回避するには(ソフトウェアがをキャッチしbad_allocて実行を継続する場合)、最初に次のようにベクター内のスペースを予約する必要があります。

    a.va_x.reserve(a.va_x.size() + 1);  // malloc() happens here
    a.va_x.push_back(x.release());      // no `bad_alloc` possible here

そうbad_allocすれば、リソースがまだに接続されている間にそのステートメントでが発生しunique_ptr、例外が発生した場合にリソースがリークすることはありません。

そうは言っても、あなたはおそらくshared_ptr代わりに必要でした。それらは問題なくコピーできます。Aunique_ptrは、一度割り当てられたリソースが1つ忘れられた場合、関数が返すか、オブジェクトが削除された場合に使用されます。(多くの)コピーが含まれる場合、ashared_ptrはより理にかなっています。

class X
{
    typedef std::shared_ptr<X> pointer_t;
    [...]
}

class A
{
    std::vector<X::pointer_t> va_x;
}

X::pointer_t x(new X());
A a;
a.va_x.push_back(x); // much cleaner and the pointer is still managed
于 2018-06-08T01:05:07.340 に答える