智能指针

作者: jdzhangxin | 来源:发表于2017-07-30 00:15 被阅读98次

指针的危害

  • 指针未初始化
  • 野指针
  • 内存泄漏

参考阅读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相似。
  • 本质:
    将指针封装为类对象成员,并在析构函数里删除指针指向的内存。
  • 不同:
    • auto_ptrunique_ptrscoped_ptr马上删除。
    • shared_ptr计数为0删除。
    • weak_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

  • 作用
    代替auto_ptr,不复制与赋值。

3. scoped_ptr

  • 作用
    unique_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 避免悬空指针。

  • 方法一
    boost::shared_ptr<std::string> sp(new std::string("method1");
    // 从shared_ptr构建出来
    boost::weak_ptr<std::string>wp(sp);
    // 再从shared_ptr获取回去
    boost::shared_ptr<std::string> p = wp.lock();
    
  • 方法二
    // 方法二
    boost::shared_ptr<std::string> sp(new std::string("method1");
    // 从shared_ptr构建出来
    boost::weak_ptr<std::string>wp(sp);
    // 再从shared_ptr获取回去
    boost::shared_ptr<std::string> p(wp);
    

总结

智能指针的特性

智能指针 管理同一个对象 可拷贝 可复制 所有权 成为容器元素 管理数组指针
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

内存管理技术

实践

有关智能指针的使用规则

  • Effective C++
    条款17:以独立语句将newed对象置于智能指针
  • Effective STL
    条款8:永不建立auto_ptr的容器
  • Exceptional C++
    条款37:auto_ptr
  • More Exceptional C++
    条款21:未管理指针存在的问题,之二:使用 auto_ptr
    条款29:使用 auto_ptr
    条款30:智能指针成员,之一:auto_ptr 存在的问题
  • Effective Modern C++
    条款18: 使用std::unique_ptr来管理独占所有权的资源
    条款19: 使用std::shared_ptr来管理共享所有权的资源
    条款20: 使用std::weak_ptr替换会造成指针悬挂的类std::shared_ptr指针
    条款21: 比起直接使用new优先使用std::make_uniquestd::make_shared

相关文章

  • 目录

    智能指针(1) 智能指针(2) 智能指针(3) 智能指针之使用 容器 - vector(1) 容器 - vecto...

  • 智能指针到Android引用计数

    智能指针 LightRefBase RefBaseStrongPointerWeakPointer 智能指针 这是...

  • C++面试重点再梳理

    智能指针 请讲一下智能指针原理,并实现一个简单的智能指针 智能指针其实不是一个指针。它是一个用来帮助我们管理指针的...

  • C++研发工程师笔试题/面试题(1-10)

    1. (1) 简述智能指针的原理;(2)c++中常用的智能指针有哪些?(3)实现一个简单的智能指针。 简述智能指针...

  • 第十六章 string类和标准模板库(2)智能指针模板类

    (二)智能指针模板类 智能指针是行为类似指针的类对象,但这种对象还有其他便于管理内存的功能。 1.使用智能指针 (...

  • Rust for cpp devs - 智能指针

    与 cpp 类似,Rust 也有智能指针。Rust 中的智能指针与引用最大的不同是,智能指针 own 内存,而引用...

  • C++ 引用计数技术及智能指针的简单实现

    1.智能指针是什么 简单来说,智能指针是一个类,它对普通指针进行封装,使智能指针类对象具有普通指针类型一样的操作。...

  • 智能指针

    1. 什么是智能指针? 智能指针是行为类似于指针的类对象,但这种对象还有其他功能。 2. 为什么设计智能指针? 引...

  • chrome中智能指针使用

    chrom中智能指针的概述和作用 chrome中智能指针的用法和总结 包含如下四种智能指针:scoped_ptr ...

  • c++智能指针用法

    智能指针是什么 智能指针是c++中有四个智能指针:auto_ptr、shared_ptr、weak_ptr、uni...

网友评论

    本文标题:智能指针

    本文链接:https://www.haomeiwen.com/subject/tchqlxtx.html