表示するものは、実際にはoperator=
必要な構文を有効にしません。shared_ptr<int> p = new int;
T*のshared_ptrのコンストラクターとshared_ptrのコピーコンストラクターを使用します。shared_ptrにはこれらの両方がありますが、T *のコンストラクターがであるため、構文は機能しませんexplicit
。
この理由は、その構築std::shared_ptr<int> test = new int;
が暗黙的に実行できる場合、shared_ptrが、明示的に要求することなく、ポインターの所有権を取得できることを意味するためです。Nawazは、これが本当にエラーを起こしやすい理由の1つを示しています。使用しているポインタが、知らないうちにどこかでshared_ptrに突然採用されて、下から破壊されないように注意する必要があります。
この危険な暗黙の構造を示す例を次に示します。
#include <iostream>
template<typename T>
struct owning_pointer {
T *t;
owning_pointer(T *t) : t{t} {}
~owning_pointer() {
std::cout << t << " deleted\n";
delete t;
}
};
void foo(owning_pointer<int> thief) {}
int main() {
int *i = new int;
std::cout << i << " allocated\n";
foo(i);
}
出力は次のようになります。
0x10d400880 allocated
0x10d400880 deleted
explicit
そして、 owning_ptrのコンストラクターに追加したときに発生するエラーを確認してください。私は得る:
main.cpp:18:5: error: no matching function for call to 'foo'
foo(i);
^~~
main.cpp:13:6: note: candidate function not viable: no known conversion from 'int *' to 'owning_pointer<int>' for 1st argument;
void foo(owning_pointer<int> thief) {}
^
また、同じエラーの可能性なしに割り当てるための完全に単純な方法がすでにいくつかあるため、T*からの暗黙的な構築を許可する必要はありません。
std::shared_ptr<int> test(new int); // one extra character isn't a hardship. I typically prefer () construction anyway.
std::shared_ptr<int> test{new int}; // although I might start preferring {} construction in C++11
auto test = std::make_shared<int>(); // this is slightly different in that the allocated int is zero-initialized
reset()
メンバーshared_ptrを初期化する場合は、代入を使用する代わりに、またはコンストラクターの本体で、初期化子リストで初期化できます。
struct foo {
std::shared_ptr<int> m_meh;
foo()
: m_meh(new int)
{
// no need for m_meh.reset(new int) here
}
};
これoperator=
を可能にするのは次のとおりです。
shared_ptr<int> s;
s = new int;
これは、T *からのshared_ptrの暗黙的な構築ほどエラーが発生しやすいようには見えませんが、実際に価値があることもわかりません。