C++智能指针的使用

来源:互联网 发布:互联网 中文域名 编辑:程序博客网 时间:2024/05/17 09:39

C++使用new在堆上动态分配内存,若程序员忘记回收内存即delete释放内存,在执行过程中会内存泄露。针对这种常见错误,C++98提出了auto_ptr,C++11摒弃了auto_ptr,提出了另外两种解决方案unique_ptr和shared_ptr。auto_ptr、unique_ptr和shared_ptr组成了3个智能指针模板类,它们都定义了类似指针的对象,可以将new获得的地址直接或间接的赋值给该对象。当智能指针过期时调用类的析构函数delete释放内存空间,从而实现辅助程序员以减少错误的功能。如下所示为C++primer中智能指针和常规指针在内存分配及释放过程中的比较示意图。


使用智能指针时,需包含<memory>头文件,使用auto_ptr需要编译器支持C++98,unique_ptr和shared_ptr需要编译器支持C++11。

智能指针的定义及初始化如下:

auto_ptr<int> p(new int);

unique_ptr<double> q(new double);

shared_ptr<long> r(new long);

3个智能指针都有显示构造函数,该构造函数将指针作为参数,所以不允许将指针自动转换为智能指针对象,如下例所示:



针对智能指针在复制传递过程中,存在两个指针指向同一块内存区域,有可能释放两次的问题,auto_ptr和unique_ptr提出了一种建立所有权的概念,对于特定的内存对象,只能有一个智能指针指向它,所以规定复制过程中转让所有权,只能由具有所有权的指针释放该对象内存。shared_ptr采用引用计数的方法,即在赋值过程中计数加1,而指针过期时计数减1,仅当最后一个指针过期时才使用delete释放内存。

auto_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
auto_ptr<int> q=p;
cout<<*q<<endl;
// cout<<*p<<endl;//Error...

以上代码中将p指针赋值给q,因此q获得p的所有权,再访问p指针时程序会出现错误,这也是C++11摒弃auto_ptr的原因。

shared_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
shared_ptr<int> q=p;
cout<<*q<<endl;
cout<<*p<<endl;//No Error...

采用shared_ptr即可解决以上问题,在赋值的过程中该对象的引用计数加1,两者都能访问该对象,同时在过期时引用计数依次减1,最后一个指针才释放内存。

使用unique_ptr不允许将指针复制,如下代码在编译过程中会报错,相比于auto_ptr中潜在的悬挂指针更安全。

unique_ptr<double> r(new double);
*r=9.78347;
cout<<*r<<endl;
unique_ptr<double> u(new double);
u=r;//Error

此外,相比于auto_ptr,unique_ptr还有另一个优点,它有一个可用于数组的变体:

unique_ptr<int []> a(new int(5));
for(int i=0;i<5;i++){
a[i]=100-i;
}
for(int j=0;j<5;j++){
cout<<a[j]<<endl;
}

unique_ptr指针a过期时会调用delete []来释放内存。

总结如下:使用new分配内存时,才能使用auto_ptr和shared_ptr,使用new[]分配内存时,不能使用它们。不使用new分配内存时不能使用auto_ptr和shared_ptr,不使用new和new[]时,不能使用unique_ptr。在选择智能指针时,若程序需要使用多个指针指向同一对象,需采用shared_ptr指针,否则,采用unique_ptr智能指针。


1 0
原创粉丝点击