总结
1、C++98中引入,C++11中弃用,C++17中被移除
2、赋值时权限转移,因为赋值运算符重载导致,简单理解就是在赋值时,他先把自己的指针给别人,然后把自己设置成null , 相当于国家军委主席权利交接,一旦交出去自己就没有权利调用军队了;
3、不能指向同一个内存,析构函数导致
4、容器不能很好的支持auto_ptr类。容器内元素的类型约束为元素类型必须支持赋值运算(引用不支持赋值,所以引用类型不能被放入容器)
5、不能作为参数传递,引用和指针可以;
代码
Auto_ptr源码:
template <class _Ty>
class auto_ptr { // wrap an object pointer to ensure destruction
public:
using element_type = _Ty;
explicit auto_ptr(_Ty* _Ptr = nullptr) noexcept : _Myptr(_Ptr) {}
auto_ptr(auto_ptr& _Right) noexcept : _Myptr(_Right.release()) {}
auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept {
_Ty* _Ptr = _Right._Ref;
_Right._Ref = nullptr; // release old
_Myptr = _Ptr; // reset this
}
template <class _Other>
operator auto_ptr<_Other>() noexcept { // convert to compatible auto_ptr
return auto_ptr<_Other>(*this);
}
template <class _Other>
operator auto_ptr_ref<_Other>() noexcept { // convert to compatible auto_ptr_ref
_Other* _Cvtptr = _Myptr; // test implicit conversion
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = nullptr; // pass ownership to auto_ptr_ref
return _Ans;
}
template <class _Other>
auto_ptr& operator=(auto_ptr<_Other>& _Right) noexcept {
reset(_Right.release());
return *this;
}
template <class _Other>
auto_ptr(auto_ptr<_Other>& _Right) noexcept : _Myptr(_Right.release()) {}
auto_ptr& operator=(auto_ptr& _Right) noexcept {
reset(_Right.release());
return *this;
}
auto_ptr& operator=(auto_ptr_ref<_Ty> _Right) noexcept {
_Ty* _Ptr = _Right._Ref;
_Right._Ref = 0; // release old
reset(_Ptr); // set new
return *this;
}
~auto_ptr() noexcept {
delete _Myptr;
}
_NODISCARD _Ty& operator*() const noexcept {
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2
return *get();
}
_NODISCARD _Ty* operator->() const noexcept {
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2
return get();
}
_NODISCARD _Ty* get() const noexcept {
return _Myptr;
}
_Ty* release() noexcept {
_Ty* _Tmp = _Myptr;
_Myptr = nullptr;
return _Tmp;
}
void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer
if (_Ptr != _Myptr) {
delete _Myptr;
}
_Myptr = _Ptr;
}
private:
_Ty* _Myptr; // the wrapped object pointer
};
比较重要的函数如下,我们只要研究以下函数即可:
//构造函数
explicit auto_ptr(_Ty* _Ptr = nullptr) noexcept : _Myptr(_Ptr) {}
//拷贝构造函数
auto_ptr(auto_ptr& _Right) noexcept : _Myptr(_Right.release()) {}
//赋值运算符重载
auto_ptr& operator=(auto_ptr& _Right) noexcept {
reset(_Right.release());
return *this;
}
//析构函数
~auto_ptr() noexcept {
delete _Myptr;
}
//release函数,release函数太骚了
//先用一个临时变量保存原有指针,然后将_Myptr设置成null,最后返回临时变量
_Ty* release() noexcept {
_Ty* _Tmp = _Myptr;
_Myptr = nullptr;
return _Tmp;
}
//重置函数
void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer
if (_Ptr != _Myptr) {
delete _Myptr;
}
_Myptr = _Ptr;
}
3、不能指向同一个内存,析构函数导致
int main()
{
int* p = new int(12);
auto_ptr<int> aptr1(p);
auto_ptr<int> aptr2(p);
return 0;
//在析构的时候aptr1会把p的内存delete掉,aptr2再次去delete p的内存的时候就会出现问题
}
总结
重要的总结再重申一遍
1、C++98中引入,C++11中弃用,C++17中被移除
2、赋值时权限转移,因为赋值运算符重载导致,简单理解就是在赋值时,他先把自己的指针给别人,然后把自己设置成null , 相当于国家军委主席权利交接,一旦交出去自己就没有权利调用军队了;
3、不能指向同一个内存,西沟函数导致
4、容器不能很好的支持auto_ptr类。容器内元素的类型约束为元素类型必须支持赋值运算(引用不支持赋值,所以引用类型不能被放入容器)
5、不能作为参数传递,引用和指针可以;