智能指针(smart pointer):
智能指针是其实是一个对象A,它带有一个模针成员变量m_p.用该A管理m_p,通过这种管理机制,可以防止由于new而导致的内存泄漏.
智能指针对象在使用时像指针一样.同时也具有一般对象的所有特征.如果要注意以下几点:
1,对象之间的赋值:若有A=B,则在赋值时,
首先要松查是否为自身赋值.如果不是,则释放A对象成员指针的内存空间,
然后要将B中的成员指针赋值于A的成员指针,
接着将B中的成员指针置为空,这样可以避免多个指针同时指向一个内存空间而产生多次析构此内存空间的错误.
所以,重载的赋值函数一般如下:
operator =(Test& source_object); 此处不能为const 对象的引用,这是因为要修改source_object 的成员指针为空.
2,对于copy constroctor也有与operator=类似的情况.只不过不要释放A成员指针的内存空间,.
3,关于member template的问题,它往往用于兼容模板对象之间的相互赋值,copy constroctor.我们可以将它看成是个模板类(一个类).
譬如:auto_ptr<B>,这就是一个类名称
另:VC7.0中,成员模板的定义和实现必须放在类的定义中.
注:member template不能为static 或virtual
4,智能指针中必须重载的几个运算符: -> *
这样做的目的就是将对象模仿成指针的行为.
如下:
T* operator ->()
{return m_p;}
特别注意:
object->m_p;== (object.operator->())->m_p;
T& operator *()
{return *m_p;}
下面的程序演示smart pointer的基本使用:
#include"iostream"
using namespace std;
template<class T>
class auto_ptr
{
public:
auto_ptr( T *p=0)
{
m_p=p;
}
//由auto_ptr<T> 来复制构造该auto_ptr<T>对象.
auto_ptr(auto_ptr<T>& source_object)
{
m_p=(T*)( source_object.get());
source_object.m_p=0; //
}
//由auto_ptr<M>来构造该auto_ptr<T>对象.
template<class M>
auto_ptr(auto_ptr<M> &source_object) //此处的对象为非const 对象的引用.
{
m_p=(T*)( source_object.get());
source_object.m_p=0; //
}
//析构....
~auto_ptr()
{
if (m_p!=0)
Release();
}
//由auto_ptr<T>赋值于auto_ptr<T>对象.
auto_ptr<T>& operator=(auto_ptr<T> &source_object)
{
Release();
m_p=(T*)(source_object.get());
return *this;
}
//由auto_ptr<M>赋值于auto_ptr<T>对象.
template<class M>
auto_ptr<T>& operator=(auto_ptr<M> &source_object)
{
Release();
m_p=(T*)(source_object.get());
return *this;
}
//delete m_p;
void Release()
{
if (m_p!=0)
delete m_p;
m_p=0;
}
T* get()
{
return m_p;
}
// from auto_ptr<T> convert to auto_ptr<M>
//声明:1 由于上面提供从auto_ptr<M>构造auto_ptr<T>的构造函数.所以,在实际上,不必给出下面的隐式类型转换函数.
// 2 VC不支持这个隐式转换特性.
template<class M>
operator auto_ptr<M>()
//如果M和T类型不一致时,将无法进行自动的类型转换.如:auto_ptr<int> 与auto_ptr<float>
{
return auto_ptr<M>(m_p);
//此处困惑:::
// return auto_ptr<M>(m_p); 这是more effective C++中的写法,当执行此语句时,会构造出一个新auto_ptr<M>的对象,而this对象的m_p并未释放.这样两个对象的m_p指向共一个变量,???
//应该这样:
//temp auto_ptr<M>(get());
//Release();
//return temp;
}
T* operator ->()
{
return m_p;
}
const T* operator->() const
{
return m_p;
}
//此处注意为T&,这样可以实现左值.
T& operator *()
{
return *m_p;
}
const T& operator *() const
{
return *m_p;
}
public:
T *m_p;
};
class test
{
public:
test(int data)
{
m_data=data;
}
int& operator->()
{
return m_data;
}
operator int()
{
return m_data;
}
public:
int m_data;
};
class A
{
public:
A(int data)
{
m_data=data;
}
private:
int m_data;
};
class B:public A
{
public:
B(int data):A(data*2),m_data(data)
{
;
}
private:
int m_data;
};
class C:public A
{
public:
C(int data):A(data*3),m_data(data)
{
;
}
private:
int m_data;
};
void test_member_template(const auto_ptr<A>& source_object)
//此处一定要加const,因为对象隐式转换后生成的对象为临时对象.临时对象的生存周期将不由程序员决定,其值不能被修改.
{
//source_object.get();
}
void test_member_template2(const auto_ptr<int>& source_object)
//此处一定要加const,因为对象隐式转换后生成的对象为临时对象.临时对象的生存周期将不由程序员决定,其值不能被修改.
{
;
}
void main()
{
auto_ptr<C> object2(new C(3));
test_member_template(object2);
//将调用member template constructor 构造出auto_ptr<A> 对象.注意,函数执行后,将导致object2变为为空壳对象.要避免这种隐式的模板对象构造.
auto_ptr<test> object(new test(15));
int data=object.operator->()->m_data;
//等价于: data=object.operator->()->operator->();
cout<<data;
auto_ptr<int> object_int(new int(999));
auto_ptr<int> object_int_2(new int(333));
object_int_2=object_int; //operator =
object_float=object_int; //operator = by member template
test_member_template2(object_int); //copy constructor
test_member_template2(object_float);//call constructor by member template.
//注意,函数执行后,将导致object2变为为空壳对象.要避免这种隐式的模板对象构造.
cout<<*object_float<<endl;;
auto_ptr<float> object_2=object_float;
//此处调用 copy constructor
cout<<*object_2<<endl;
}