C++2.0

智能指针

2017-07-30  本文已影响98人  jdzhangxin

指针的危害

参考阅读C/C++指针使用常见的坑

智能指针分类

智能指针 进入C++标准的版本 STL头文件 boost头文件 说明
auto_ptr C++03 <memory> <boost/auto_ptr.hpp> 尽量避免使用
unique_ptr C++11 <memory> <boost/unique_ptr.hpp> 管理单个堆内存对象,独享所有权,不允许赋值和拷贝,不能用于管理数组对象
shared_ptr C++11 <memory> <boost/shared_ptr.hpp> 引用计数智能指针,共享所有权
weak_ptr C++11 <memory> <boost/weak_ptr.hpp> shared_ptr的观察者,只进行引用而不改变引用计数,用来解决shared_ptr的循环引用问题
scoped_ptr - - <boost/scoped_ptr.hpp> 作用域智能指针,功能与unique_ptr相似。

智能指针是来解决指针危害的。


1. auto_ptr

#include <iostream>
#include <memory>
using namespace std;
int main(){
    int* pn = new int(10);
    auto_ptr<int> ap(pn);
    cout << *ap << endl;
}
#include <iostream>
#include <memory>
using namespace std;
class Test{
public:
    Test(){cout << __func__ << endl;}
    ~Test(){cout << __func__ << endl;}
    void Func(){cout << __func__ << endl;}
};
int main(){
    Test* pt = new Test;
    auto_ptr<Test> apt(pt);
    apt->Func();
}

通过valgrind可以看到没有内存泄露,指针可以被正常释放。

  1. 两个auto_ptr不能同时拥有同一个对象
#include <memory>
using namespace std;
int main(){
    int* pn = new int(10);
    auto_ptr<int> ap1(pn);
    auto_ptr<int> ap2(pn);
}
  1. auto_ptr不能管理数组指针
#include <memory>
using namespace std;
int main(){
    int*pa=new int[10];
    auto_ptr<int>ap(pa);
}
  1. auto_ptr被拷贝或被赋值后,失去对原指针的管理.这种情况被称为指针所有权传递。

赋值的情况

#include <iostream>
#include <memory>
using namespace std;
int main(){
    int*p = new int(10);
    auto_ptr<int> ap1(p);
    cout<< *ap1 <<endl;
    auto_ptr<int> ap2=ap1;
    cout<< *ap1 <<endl;
}

拷贝的情况

#include <iostream>
#include <memory>
using namespace std;
void Func(auto_ptr<int> ap){
    cout << *ap << endl;
}
int main(){
    int*p = new int(10);
    auto_ptr<int> ap(p);
    cout<< *ap <<endl;
    Func(ap);
    cout<< *ap <<endl;
}
  1. auto_ptr不能作为容器对象,因为STL容器中的元素经常要支持拷贝,赋值等操作。
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
int main(){
    int*p = new int(10);
    auto_ptr<int> ap(p);
    vector<auto_ptr<int> > vec;
    vec.push_back(ap);
}

2. unique_ptr


3. scoped_ptr


4. shared_ptr

循环引用问题

#include <string>  
#include <iostream>  
#include <boost/shared_ptr.hpp>  
#include <boost/weak_ptr.hpp>  
  
class parent;  
class children;  
  
class parent {  
public:  
    ~parent() { std::cout <<"destroying parent\n"; }  
public:  
    boost::shared_ptr<parent> children;  
};  
  
class children {  
public:  
    ~children() { std::cout <<"destroying children\n"; }  
public:  
    boost::shared_ptr<children> parent;  
};  
void test(){  
    boost::shared_ptr<parent> father(new parent());  
    boost::shared_ptr<children> son(new children);  
    father->children = son;  
    son->parent = father;  
}  
void main(){  
    std::cout<<"begin test...\n";  
    test();  
    std::cout<<"end test.\n";  
}  

5. weak_ptr

解决shared_ptr循环引用问题

#include <string>  
#include <iostream>  
#include <boost/shared_ptr.hpp>  
#include <boost/weak_ptr.hpp>  
  
class parent;  
class children;  
class parent {  
public:  
    ~parent() { std::cout <<"destroying parent\n"; }  
public:  
    boost::weak_ptr<children> children;  
};
class children {  
public:  
    ~children() { std::cout <<"destroying children\n"; }
public:  
    boost::weak_ptr<parent> parent;  
};
void test(){  
    parent_ptr father(new parent());  
    boost::shared_ptr<children> son(new children);  
    father->children = son;  
    son->parent = father;  
}
void main(){  
    std::cout<<"begin test...\n";  
    test();  
    std::cout<<"end test.\n";  
}  

智能指针weak_ptr主要用来协助shared_ptr。不参与引用计数,但是有以下好处:
1 打破递归的依赖关系
2 使用一个共享的资源但是不要所有权,不添加引用计数
3 避免悬空指针。


总结

智能指针的特性

智能指针 管理同一个对象 可拷贝 可复制 所有权 成为容器元素 管理数组指针
auto_ptr NG OK OK 传递 NG NG
unique_ptr NG NG NG 独享 NG NG
scoped_ptr NG NG NG 独享 NG NG
shared_ptr NG OK OK 共享 OK NG
weak_ptr NG OK OK 共享 OK NG

虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案。
如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。
因此,不要认为只要使用了智能指针便能杜绝内存泄漏。

C++:Boost库_weak_ptr

内存管理技术

实践

有关智能指针的使用规则

上一篇 下一篇

猜你喜欢

热点阅读