• C++ 智能指针


    智能指针:shared_ptr类

    shared_ptr是一个模板类,智能指针本质是个对象,有一些方法可以调用。

    shared_ptr<int> p;
    p.get();//获得指针的值(内存地址)
    p.use_count();//有几个智能指针指向这个内存地址
    p.unique();//如果p.use_count()==1,他返回true
    

    这个类也定义了解引用运算符(*)和箭头运算符(->),目的是像使用指针一样使用智能指针。

    *p;
    p->func();//等价(*p).func();
    

    make_shared() 函数

    智能指针有三种初始化方式

    shared_ptr<int> p(new int);//用new返回的指针来初始化,但这个构造函数是explicit的,因此,普通指针无法隐式转换成智能指针。
    shared_ptr<int> q(p);//用另一个智能指针初始化
    shared_ptr<int> p(make_shared<int>(10)); //使用make_shared();他也是一个模板,需要指定类型,后边的括号相当于调用构造函数
    //也可以用auto
    auto p = make_shared<int>(10);
    

    动态内存会随着智能指针的生命周期而自动释放,当没有一个智能指针指向某块内存,他就会自动释放。也就是p.use_count() == 0,当然这个代码不可能运行成功,只是方便理解。

    注意事项:

    1. 不要混用智能指针和普通指针,你很难注意智能指针什么时候会自动释放,这时再用普通指针访问会发生错误。

    2. 不要用智能指针的get()函数来初始化另一个智能指针,这种方法不会增加use_count,因此会double free。

      int main()
      {
      	shared_ptr<C> p(make_shared<C>());
      	shared_ptr<C> q(p.get());
      	cout << p.use_count();//输出1
      	getchar();
      	return 0;
      	//程序结束p和q都会释放内存,double free
      }
      

    使用自己的释放操作

    引用C++ primer里的例子,假如shared_ptr指向的是一个网络连接,那么我们希望当这个连接不再使用的时候能够自动释放,这就需要自己定义释放函数。

    void end_connection(connection *p)
    {
        //释放连接
    }
    void f(destination &d)
    {
        connection c = connect(d);
        shared_ptr<connection> p(&c, end_connection);
        //使用连接
        //从f退出时,connection会自动调用end_connection关闭
    }
    

    unique_ptr

    shared_ptr智能指针可以不同的几个智能指针指向同一块内存,而unique_ptr只允许一个智能指针(不管是shared_ptr还是unique_ptr)指向这块内存。要想将这块内存变成普通的智能指针,使用p.release()

    unique_ptr<T> up(new T);
    shared_ptr<T> sp(up.release());
    up.reset(new int);//重新绑定一个内存地址
    

    unique_ptr使用自己的释放操作

    unique_ptr<T, D> p(new T, d);
    //D是可调用对象的类型,d是D类型的一个对象
    //下边是个例子
    void end_connection(connection *p)
    {
        //释放连接
    }
    void f(destination &d)
    {
        connection c = connect(d);
        unique_ptr<connection, decltype(end_connection)*> p(&c, end_connection);
        //使用连接
        //从f退出时,connection会自动调用end_connection关闭
    }
    
  • 相关阅读:
    一篇文章看懂mysql中varchar能存多少汉字、数字,以及varchar(100)和varchar(10)的区别
    SQL处理下划线分割的两边数字都分别增加值
    [LeetCode]Binary Tree Zigzag Level Order Traversal
    [LeetCode]Binary Tree Level Order Traversal
    [LeetCode]Candy
    [LeetCode]Single Number II
    [LeetCode]Single Number
    [LeetCode]Copy List with Random Pointer
    [LeetCode]Link List Cycle II
    [LeetCode]Link List Cycle
  • 原文地址:https://www.cnblogs.com/hellozhangjz/p/15999807.html
Copyright © 2020-2023  润新知