まず、std::auto_ptr に 3 つのバージョンがあることを確認してください。
次のような std::auto_ptr の最初のバージョン:
template<class T>
class auto_ptr
{
public:
explicit auto_ptr(T *p = 0): pointee(p) {}
// copy constructor member
// template: initialize a new auto_ptr with any compatible auto_ptr
template<class U> auto_ptr(auto_ptr<U>& rhs): pointee(rhs.release()) {}
~auto_ptr() { delete pointee; }
// assignment operator
// member template assign from any compatible auto_ptr
template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs)
{
if (&rhs != this)
{
reset(rhs.release());
}
return *this;
}
T& operator*() const { return *get(); }
T* operator->() const { return get(); }
// return value of current dumb pointer
T* get() const { return pointee; }
// relinquish ownership of current dumb pointer and return its value
T* release() { T* p = pointee; pointee = 0; return p; }
// delete owned pointer,assume ownership of p
void reset(T *p = 0)
{
if (p != pointee)
{
delete pointee;
pointee = p;
}
}
private:
T* pointee;
};
実装は簡単ですが、インターフェイスのみです。
私のコードは次のようになります:
auto_ptr<int> foo()
{
auto_ptr<int> p(new int(1));
return p;
}
int main()
{
auto_ptr<int> p;
p = foo();
return 0;
}
私の見解では、私のテスト コードはコンパイラを通過できません。しかし、それは合格し、実行すると、ポンターの削除で2回壊れました。
アセンブリ コードをトレースすると、次のようなフローが見つかりました。メモリ アドレスは略して下位 16 ビットです。
ctor: f8e4
new: 6bf0
ctor: f7d4
copy ctor: f7d4 -> f80c
dctor: f7d4 (NULL)
delete: 0
lea ecx, [ebp-0ECh] // f8e4: memory-> 6bf0
dctor: f80c (6bf0)
delete: 6bf0
dctor: f8e4 (6bf0) // twice delete
コードのようです: p = foo(); 一時オブジェクトを ctor し、foo() で新しいメモリを保持します。
重要な点は、なぜ p = foo() が p.operator=() を呼び出す以外に p.pointee を変更するのかということです。
1 つ目の auto_ptr の実装を追加します。
ネットの友達と話して、彼はmybe コンパイラが生成することを指摘しました:
auto_ptr<T>& operator=(auto_ptr<T>& rhs)
使用以外
template<class U> auto_ptr<T>& operator=(auto_ptr<U>& rhs);
std::auto_ptr には 2 つの operator= があることがわかりました。そして、コンパイラのヒント:「「auto_ptr」は「auto_ptr&」に変換できません」ながら、手動でインターフェイスに追加してテストします。
それが鍵です!!! 次に、理由を見つける必要があります。
ユーザーがクラス型の operator= を定義していない場合、コンパイラはそれを生成します。そして、他の operator= と比較して、より特別なものを選択してください!
解決しました!あなたのすべての答えを考えます!コメントありがとうございます!