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; }
通过上面可以看到,每一次“=”都会转移控制权。
再看看以下代码:
void bad_print(auto_ptr<int>p) { if(p.get()==NULL) { cout<<"NULL"<<endl; } else { cout<<*p<<endl;; } }
只要运行:
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;