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