首先请确保您知道 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;
}
在我看来,我的测试代码无法通过编译器。但是它通过了,当我运行它时,它因为删除一个指针而损坏了两次。
我跟踪汇编代码,发现如下流程,内存地址简称为低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.pointee,而不是调用 p.operator=() ?
我添加了第一个 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 有两个 operator=。我测试手动将其添加到界面,而编译器提示:“'auto_ptr'不能转换为'auto_ptr &'”。
这就是钥匙!!!那么我需要找到为什么!
当用户没有为类类型定义 operator= 时,编译器将生成一个。并与其他operator=比较,选择一个更特别的!
解决了!想想你所有的答案!谢谢你们的评论!