——C++ 智能指针 std::auto_ptr 分析
背景介绍:
ps:智能指针就是RAll机制的一种应用,智能指针从根本上来说是一个对象
auto_ptr是什么?
ps:头文件:#include<memory>
初始化auto_ptr的方法
1)构造函数
int *p=new int(33); auto_ptr<int> aptr(p);
auto_ptr<int> aptr(new int(33));
利用已经存在的智能指针来构造新的智能指针
auto_ptr<string> p1(new string("name")); auto_ptr<string> p2(p1);
3)赋值
利用已经存在的智能指针来构造新的智能指针
auto_ptr<string> p1(new string("name")); auto_ptr<string> p2(new string("sex")); p1=p2;
在赋值之前由p1指向的对象被删除,赋值之后p1拥有字符串sex的内存所有权,p2不再被用来指向sex字符串对象
ps:可以直接定义一个空的智能指针,默认值为0
防止两个auto_ptr对象拥有同一个对象(同一块内存)
因为auto_ptr的内存所有权是独占的,所以以下代码存在问题
int *p=new int(10); auto_ptr<string> p1(p); auto_ptr<string> p2(p);因为p1和p2都认为p是由它管,在析构时都试图删除p,两次删除同一个对象的行为在C++标准中是未定义的,我们必须防止这样使用auto_ptr
警惕auto_ptr作为参数
void f(auto_ptr<int> aptr) { cout<<*aptr<<endl; } int main() { auto_ptr<int> aptr(new int(10)); f(aptr); cout<<*aptr<<endl;//错误,经过f函数调用,原有的aptr已经不再拥有任何对象了 }
2)参数为引用或指针,虽然不会存在上述的拷贝过程,但是我们并不知道函数对传入的auto_ptr做了什么,如果其中的某种操作使其失去了对象的所有权,那么还是会导致致命的执行错误
结论:const reference是auto_ptr作为参数传递的底线
auto_ptr不能初始化为指向非动态内存
因为delete表达式被应用在指向非动态内存的指针上,这是C++未定义的程序行为
auto_ptr常用的成员函数
int main() { int *p=new int(10); cout << "the adress of p: "<< p << endl; auto_ptr<int> aptr(p); cout << "the adress of aptr: " << &aptr << endl; cout << "the adress of the object which aptr point to: " << aptr.get() << endl; } 程序运行结果: the adress of p: 0xb50f80 the adress of aptr: 0x69fed8 the adress of the object which aptr point to: 0xb50f80
2)reset:重新设置auto_ptr指向的对象,类似于赋值操作,但是赋值操作不允许将一个普通指针直接赋值给auto_ptr,而reset允许。
reset(0)可以释放对象,销毁内存
int main() { auto_ptr<string> aptr(new string("name")); aptr.reset(new string("sex")); cout<<*(aptr.get())<<endl; cout<<*aptr<<endl; } 程序运行结果: sex sex
3)release:返回auto_ptr指向的那个对象的内存地址,并且释放这个对象的所有权
用此函数初始化auto_ptr可以避免两个auto_ptr对象指向同一个对象的情况
int main() { auto_ptr<string> aptr(new string("name")); auto_ptr<string> aptr1(aptr.get());//这是两个auto_ptr拥有同一个对象 auto_ptr<string> aptr2(aptr.release());//release可以先释放所有权,这样就不会指向同一个对象 }该函数不会释放对象,仅仅会归还所有权
千万不要把auto_ptr对象放在容器中
使用总结:
1)两个auto_ptr对象不会同时指向同一个内存,要明白两个auto_ptr对象赋值会发生什么
2)auto_ptr对象存储的指针应该为NULL或者指向一个动态内存块
3)auto_ptr对象存储的指针应该指向单一物件(是new出来的,而不是new[]出来的,不支持指向指针数组)
4)千万不要把auto_ptr对象放在容器中
5)当将auto_ptr作为参数传递时,const reference是auto_ptr作为参数传递的底线
结论:使用一个auto_ptr的限制很多,还不能用来管理堆内存数组,使用不当会引发很多的问题,其中一些设计也不符合C++设计的思想,所以产生了boost的智能指针,boost的智能指针可以解决上面的问题!下节将讨论boost智能指针
auto_ptr的本质是管理权限的转移!