智能指针:Effective c++总结

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指向同一个对象,
	//如果被销毁已经删除之物,那么往往会很严重

}

所以auto_ptr采样更加富有弹性解法,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*指针
//}


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>
}

现在就成功的首先编译器会在smarptr<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;
}

template<class T>
class SmartPtToConst{
protected:
union{
const T*constPointee;
T*pointee;
};
};


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值