C++标准库---智能指针auto_ptr初探

1.智能指针auto_ptr

C++标准库程序提供的auto_ptr是一种智能型指针(smart pointer),帮助程序员防止“被异常抛出时发生资源泄漏”。注意auto_ptr只是针对一种特殊情况设计的,对于其他问题auto_ptr无能为力。

auto_ptr的接口与一般指针非常相似:operator*用来提领其所指对象,operator ->用来指向对象中的成员。当时没有定义所有指针运算符,包括(++)。


auto_ptr初始化方式:

std::auto_ptr<ClassA>ptr1(new ClassA);   //OK

std::auto_ptr<ClassA>ptr2=new ClassA;  //ERROR

例如:

std::auto_ptr<int> p(new int (42));   //OK

std::auto_ptr<int> p=new int (42);   // ERROR (切记!原因:auto_ptr的构造函数被定义为explicit)


由于一个auto_ptr会删除其所指对象,所以这个对象绝对不能同时被其他对象“拥有”。绝对不应该出现多个auto_ptr同时拥有一个对象的情况


2.auto_ptr拥有权的转移

   拷贝构造

std::auto_ptr<ClassA>ptr1(new ClassA);

std::auto_ptr<ClassA> ptr2(ptr1);

在第一个语句中,ptr1拥有了那个new出来的对象。在第二个语句中,拥有权由ptr1转交给ptr2。此后ptr2就拥有了那个new出来的对象,而ptr1不再拥有它。这样,对象就会在被delete一次---在ptr2被销毁的时候。

   赋值动作也差不多

std::auto_ptr<ClassA>ptr1(new ClassA);

std::auto_ptr<ClassA> ptr2;

ptr2=ptr1;

在这里,赋值动做将拥有权从ptr1转移至ptr2。于是,ptr2拥有了先前被ptr1拥有的那个对象。

std::auto_ptr<ClassA>ptr1(new ClassA);

std::auto_ptr<ClassA> ptr2(new ClassA);

ptr2=ptr1;

注意,拥有权的转移,实质上并非只是被简单拷贝而已。只要发生了拥有权转移,先前的拥有者(本例ptr1)就失去了拥有权,结果,拥有者一旦交出了拥有权,就两手空空,只剩一个null指针在手了。


3.拥有权的转移代码示例

//auto_ptr 智能指针 转交控制权
#include<iostream>
#include<memory>

using namespace std;

template<class T>
ostream& operator<<(ostream& strm,const auto_ptr<T>&p)//注意第二个参数是一个const reference,所以在输出期间并没有发生拥有权的转移
{
	if(p.get()==NULL)
	{
		strm<<"NULL";
	}
	else
	{
		strm<<*p;
	}
	return strm;
}

int main()
{
	auto_ptr<int> p(new int(45));
	auto_ptr<int> q;

	cout<<"after initialization:"<<endl;
	cout<<"p:"<<p<<endl;//通过重载<<运算符来输出
	cout<<"q:"<<q<<endl;

	q=p;
	cout<<"after assigning auto pointers:"<<endl;
	cout<<"p:"<<p<<endl;
	cout<<"q:"<<q<<endl;

	*q+=13;
	p=q;
	cout<<"after change and reassignment:"<<endl;
	cout<<"p:"<<p<<endl;
	cout<<"q:"<<q<<endl;

	system("pause");
	return 0;
}

运行结果:

C++标准库---智能指针auto_ptr初探_第1张图片


通过上面可以看到,每一次“=”都会转移控制权。


再看看以下代码:

void bad_print(auto_ptr<int>p)
{
	if(p.get()==NULL)
	{
		cout<<"NULL"<<endl;
	}
	else
	{
		cout<<*p<<endl;;
	}
}

原本想将auto_ptr所指的对象打印出来,实际上引发了一场灾难。

只要运行:

std::auto_ptr<int> p(new int);

*p=42;

bad_print(p);

*p=18;  //RUNTIME ERROR

只要有一个auto_ptr被当作参数,放进这个bad_print()函数,它所拥有的对象就一定会被删除。因为作为参数的auto_ptr会将拥有权转交给参数p,而当函数退出时,会删除p所拥有的对象。


那么auto_ptr以pass by reference方式传递呢?是不是万事大吉?

这种行为会让“拥有权”的概念变得难以捉摸,因为面对一个“透过reference而获得auto_ptr”的函数,你根本无法预知拥有权是否被转交。所以以by reference 方式传递auto_ptr是非常糟糕的设计,应该权利避免。


采用cosntant reference,向函数传递拥有权,可以另constant reference无法交出拥有权。事实上你无法更改任何constant reference的拥有权。

void bad_print(const auto_ptr<int>&p)


这样运行以下,不会出现问题:

std::auto_ptr<int> p(new int);

*p=42;

bad_print(p);

*p=18; 


你可能感兴趣的:(设计,标准,智能指针,pair)