1.概念
所谓smart pointers 就是看起来用起来想内建指针,提供更多机能
包括各种用途,资源管理以及自动重复写码工作
包括各种用途,资源管理以及自动重复写码工作
当你用smart pointers取代C++内建指针的时候,你会获得以下各种指针行为控制权:
构造和析构:
当指向该对象的最后一个smart pointers被销毁的时候,会删除对象。
复制和赋值:
当一个smart pointer被复制或涉及赋值动作,不管是深复制,还是指针本身的复制,或者不允许复制
解引:
所指之物的解引用
因为smart pointers有templetes必须有强烈的类型性
template<class T>
class SmartPtr{
public:
SmartPtr(T*realPtr = 0);//产生一个smart ptr指向原本已经有的dumb ptr
SmartPtr(const SmartPtr&rhs);
~SmartPtr();
SmartPtr& operator=(const SmartPtr&rhs);
T*operator->const;//解引
T&operator*()const;//解引
private:
T*pointee;
};
2.Smart pointer的如何运用
例如一个分布式的系统,某些对象在本地,而某些在远程,本地对象访问比远程访问简单而快速,让所有对象因为本地和远程处理方式的不同,可以用smart pointers
修改让看起来相同
template<class T>//指向分布式数据库(DB)内的对象
class DBPtr{
public:
DBPtr(T*realPtr = 0);//产生一个smart ptr指向DB对象
DBPtr(int id);//产生一个smart ptr指向一个DB对象
T&operator*()const;
T* operator->()const;
};
class Tuple{//一笔数据
public:
void displayEditDialog();
bool isValid()const;
};
//完成运转记录
template<class T>
class LogEntry{
public:
LogEntry(const T&objectToBeModified);
~LogEntry();
};
void editTuple(DBPtr<Tuple>&pt){
LogEntry<Tuple> entry(*pt);
do
{
pt->displayEditDialog();
} while (pt->isValid()==false);
}
3.smart pointer 的构造赋值和析构实现
smart pointer的构造行为一般比较明确,确定一个目标物,然后用smart pointer的内部指针指向它
但是赋值和 复制和析构会因为拥有权问题
考虑auto_ptr的实现问题:
template<class T>
class auto_ptr{
public:
auto_ptr(T*PTR=0):pointee(PTR){}
~auto_ptr();
private:
T*pointee;
};
class Treenode{};
//在同一个对象只能被一个auto_ptr拥有的前提
void testPtr(){
auto_ptr<Treenode>ptn1(new Treenode);
auto_ptr<Treenode>ptn2 = ptn1;
auto_ptr<Treenode>ptn3 = ptn2;
//如果只复制内部指针,那么会导致两个auto_ptr指向同一个对象,
//如果被销毁已经删除之物,那么往往会很严重
}
template<class T>
class auto_ptr{
public:
auto_ptr(auto_ptr<T>&rhs);
auto_ptr<T>&
operator = (auto_ptr<T>&rhs);
T& operator*()const{
return *pointee;
}
private:
T*pointee;
};
template<class T>
auto_ptr<T>::auto_ptr(auto_ptr<T>&rhs){
pointee =rhs.pointee;
rhs.pointee = 0;//不在拥有任何东西
}
template<class T>
auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<T>&rhs){
if (this==&rhs)
return *this;
delete pointee;
pointee = rhs.pointee;
rhs.pointee = 0;
return *this;
}
//因为被以value方式传递的时候,对象拥有权就转移了,很糟糕
//而且不能是const因为内部指针改变了
void printTreeNode(ostream&s,auto_ptr<Treenode>p){
s<<*p;
}
当这个函数调用完毕后,实参传递以后就会不指向任何东西,导致未定义的行为。
void printTreeNode(ostream&s,const auto_ptr<Treenode>&p){
s<<*p;
}
4.smart pointer实现解引用操作符
T& operator*()const{
//perform smart pointer processing
return *pointee;
}
template<class T>
T*SmartPtr<T>::operator->()const{
<span> </span>//perform smart pointer processing
<span> </span>return pointee;
}
</pre><pre name="code" class="cpp">smart pointers 是为了能够模拟内部指针的行为,内部指针因为可能指向的对象又函数
并且可能存在返回类型不是引用造成的切割问题
5.smart pointers 测试是否为Null
template<class T>
class SmartPtr{
public:
SmartPtr(T*realPtr = 0);//产生一个smart ptr指向原本已经有的dumb ptr
SmartPtr(const SmartPtr&rhs);
~SmartPtr();
SmartPtr& operator=(const SmartPtr&rhs);
T*operator->const;//解引
T&operator*()const;//解引
//加入一个opeartor void*()如果内部指针为Null 返回0
operator void*();
private:
T*pointee;
};
但是这是有问题的
//void testNull(){
// SmartPtr<apple>pa;
// SmartPtr<pear>po;
// if (pa==po)//编译成功的都转换成void*指针
//}
// SmartPtr<apple>pa;
// SmartPtr<pear>po;
// if (pa==po)//编译成功的都转换成void*指针
//}
5.将smart pointers 转换成 内部指针
template<class T>
class DBPtr{
public:
operator T*()
{
return pointee;
}
private:
T *pointee;
};
class TupleAccessors{
public:TupleAccessors(const Tuple*pt);
};
TupleAccessors merge(const TupleAccessors&ta1,const TupleAccessors&ta2);
Tuple *pt1,*pt2;
merge(pt1,pt2);
无法将两个Tuple*转换成为TupleAccessors
同时隐士转换会有问题
DBPtr<Tuple>pty = new Tuple;
delete pt;
编译器会隐士类型转换让函数调用成功 如果pt所指物会被删除两次
一次是pt 的析构函数 然后实际指针再删除一次
6.smart pointes和与继承有关的类型转换
class MusicProduct{
public:
MusicProduct(const string&title);
virtual void play()const = 0;
virtual void displayTitle()const = 0;
};
class Cassetee:public MusicProduct{
public:
Cassetee(const string&title);
virtual void play()const;
virtual void displayTitle()const;
};
class CD;public MusicProduct{
public:
CD(const string&title);
virtual void play()const;
virtual void displayTitle()const;
};
void displayAndPlay(const MusicProduct* PMP,int numTimes){
for (int i=1;i<=numTimes;++i)
{
PMP->displayTitle();
PMP->play();
}
}
void displayAndPlay(const SmartPtr<MusicProduct>&pmp,int numTimes);
void smartPtrTest(){
SmartPtr<Cassetee> funmusic(new Cassetee("Alapalooza"));
SmartPtr<CD> nightmareMusic(new CD("Disco hits of the 89"));
displayAndPlay(funmusic,10);//错误
displayAndPlay(nightmareMusic,0);//错误
//无法将smartptr<CD>和smartptr<cassttee>转换成smartptr<musicproduct>
}
class SmartPtr<Cassetee>{
public:
//新增加的转换操作符
operator SmartPtr<MusicProduct>(){
return SmartPtr<MusicProduct>(pointee);
}
private:
Cassetee*pointee;
};
class SmartPtr<CD>{
public:
operator SmartPtr<MusicProduct>(){
return SmartPtr<MusicProduct>(pointee);
}
private:
CD*pointee;
};
//缺点就是要加入很多这样的转换因为一个继承层次
所以可以用一个语言扩充的性质
template<class T>
class SmartPtr{
public:
SmartPtr(T*realPtr = 0);//产生一个smart ptr指向原本已经有的dumb ptr
SmartPtr(const SmartPtr&rhs);
~SmartPtr();
SmartPtr& operator=(const SmartPtr&rhs);
T*operator->const;//解引
T&operator*()const;//解引
//重点
template<class newType>
operator SmartPtr<newType>(){
return SmartPtr<newType>(pointee);
}
//加入一个opeartor void*()如果内部指针为Null 返回0
operator void*();
private:
T*pointee;
};
void displayAndPlay(const SmartPtr<MusicProduct>&pmp,int numTimes);
void smartPtrTest(){
SmartPtr<Cassetee> funmusic(new Cassetee("Alapalooza"));
SmartPtr<CD> nightmareMusic(new CD("Disco hits of the 89"));
displayAndPlay(funmusic,10);//错误
displayAndPlay(nightmareMusic,0);//错误
//无法将smartptr<CD>和smartptr<cassttee>转换成smartptr<musicproduct>
}
再寻找隐士类型转换操作符产生这个对象
还没有的话就寻找member function templete寻找可以实例化的
class CasSingle:public Cassetee{
};
void displayAndPlay(const SmartPtr<MusicProduct>&pmp,int numTimes);
void displayAndPlay(const SmartPtr<Cassetee>&pmp,int numTimes);
SmartPtr<CasSingle> dumbMusic(new CasSingle("Achy break"));
displayAndPlay(dumbMusic,1);
//这样会错误在内部指针的时候会选择直接继承的casseetee,但是智能指针不能分辨
7.smart pointers 与 const
void testSmartConst(){
CD goodCD("flood");
SmartPtr<CD>P;
SmartPtr<const CD>p;
const SmartPtr<CD>p = &goodCD;
const SmartPtr<const CD>p = &goodCD;
}
CD goodCD("flood");
SmartPtr<CD>P;
SmartPtr<const CD>p;
const SmartPtr<CD>p = &goodCD;
const SmartPtr<const CD>p = &goodCD;
}
template<class T>
class SmartPtToConst{
protected:
union{
const T*constPointee;
T*pointee;
};
};
class SmartPtToConst{
protected:
union{
const T*constPointee;
T*pointee;
};
};