1 vc版auto_ptr智能指针实现
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
//#include<memory>
#include <vld.h>
using namespace std;
template<class _Ty>
class AutoPtr
{
public:
// 默认构造函数,_Ptr为空时,没有任何空间的管理权
AutoPtr(_Ty *p = 0) :_Owns(p != 0), _Ptr(p){}
// 拷贝构造函数,调用_Y.Release()保证在_Ptr成员赋值时拥有权转移出去
AutoPtr(const AutoPtr<_Ty> &_Y):_Owns(_Y._Owns),_Ptr(_Y.Release()){}
// 赋值语句
AutoPtr<_Ty>& operator=(const AutoPtr<_Ty> &_Y)
{
if (this != &_Y)
{
/* 两个智能指针的空间管理对象不同,形如
* auto_ptr<int> q1(a),q2(b);
* q1 = q2
*/
if (_Ptr != _Y._Ptr)
{
// 若拥有空间管理权,释放原来的空间
if(_Owns)
delete _Ptr;
_Owns = _Y._Owns;
}
/* 两个智能指针的空间管理对象相同,形如
* int a = new int
* auto_ptr<int> q1(a),q2(a);
* q1 = q2,空间管理对象相同时_Ptr空间不释放
* 只要保证拥有权正确转移即可
* 这里还有对_Y._Owns做判断,是要保证拥有权不会丢失
* 防止q1的拥有权为真,q2的拥有权为假从而直接赋值后
* 拥有权丢失的情况
*/
else if (_Y._Owns)
{
_Owns = true;
}
_Ptr = _Y.Release();
}
return *this;
}
// 重载* 使对象有指针取*的特性
_Ty& operator*()const
{
return *_Ptr;
}
// 重载-> 使对象有指针 -> 运算的特性
_Ty* operator->()const
{
return _Ptr;
}
// 在_Ptr成员赋值时保证拥有权转移出去
_Ty* Release()const
{
// 强转,去掉this指针的常性以改变成员_Owns的值
((AutoPtr<_Ty>*)(this))->_Owns = false;
return _Ptr;
}
~AutoPtr()
{
// 拥有权为真在析构智能指针时才能释放空间
if (_Owns)
delete _Ptr;
}
private:
/* 拥有权,拥有权为真才有资格释放智能指针管理的空间
* 为了防止在拷贝构造或赋值时,同一块空间被多个智能指针对象管理
* 造成同一块空间被多重释放,因此要保证智能指针在拷贝或赋值时拥有权
* 的正确转移,即任何时刻只能有一个智能指针对一块空间有拥有权
*/
bool _Owns;
_Ty* _Ptr;
};
class Test
{
public:
void fun()
{
cout << "Test fun" << endl;
}
};
int main()
{
int *p = new int(10);
AutoPtr<int> q(p);
AutoPtr<int> q2(q); // 拷贝构造转移空间管理权
q2 = q; // 赋值转移空间管理权
cout << *q2 << endl;
*q = 1000;
cout << *q << " " << *q2 << endl;
Test *pt = new Test;
AutoPtr<Test> t(pt);
t->fun();
AutoPtr<Test> t2;
t2 = t; // 赋值转移空间管理权
t2->fun();
system("pause");
return 0;
}
2 vc版auto_ptr缺点
在调用拷贝构造或重新赋值后,空间管理权虽然发生了转移,但是仍然能通过智能指针改变或访问其所不具有空间管理权的空间的值
int *p = new int(10);
AutoPtr<int> q(p);
AutoPtr<int> q2(q); // 空间管理已发生转移,交由q2管理
*q = 100; // q已不具有空间管理权,但是仍能访问或改变原来空间的值
cout << *q << endl;