c++ 智能指针

所需要的头文件 #include <memory>

  • shared_ptr : 允许多个指针指向同一个对象;
  • unique_ptr : 独占 所指向的对象
  • weak_ptr : 弱引用

shared_ptr独有的操作

  • make_shared函数 : 最安全的分配和使用动态内存的方法
  shared_ptr<int> p3 = make_shared<int>(42);
  cout<<*(p3.get())<<endl; //42
  shared_ptr<string> p4 = make_shared<string>(10,'9');
  cout<<*(p4.get())<<endl; // 10个9
  auto p5 = make_shared<int>(); // p5 指向一个初始化的int,初始值为0
  auto p6 = make_shared<vector<string>>(); //p6 指向一个动态分配的空vector<string>
  // 拷贝和赋值
  auto p = make_shared<int>(42);
  auto q(p);
  cout<<*(q.get())<<endl; // 42
  auto r = make_shared<int>(43);
  r = q; // r所指向的对象的引用计数器递减,没有了引用者,会自动释放
  cout<<*(r.get())<<endl; // 42 

shared_ptr和new结合使用

    shared_ptr<double> p1; 
    /*  
     *shared_ptr<T> p(q)
     * p管理内置指针q所指向的对象
     * q必须指向new分配的内存,且能够转换为T*类型
     */
    shared_ptr<int> p2(new int(42)); 
    // p2 = new int(42); 错误 不能将一个指针赋值给shared_ptr
    /*  
     *p2.reset() 若p2是唯一指向其对象的shared_ptr,reset会释放此对象
     * reset 成员经常与 unique 一起使用,来控制多个shared_ptr 共享的对象,
     * 在改变底层对象之前,我们检查自己是否是当前对象仅有的用户,如果不是,
     * 在改变之前要制作一份新的拷贝
     */
    p2.reset(new int(1024)); // p2指向一个新的对象
    cout<<*(p2.get())<<endl;
    if(!p2.unique())
    {   
        p2.reset(new int(*p2)); // 我们不是唯一用户;分配新的拷贝;
    }   
    *p2 += 22; // 现在我们知道自己是唯一的用户,可以改变对象的值
    cout<<*p2<<endl; // 1046

unique_ptr

  • 一个 unique_ptr 拥有 它所指向的对象。 与shared_ptr不同,某个时刻只能有一个unique_ptr 指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。
  • 没有类似的make_shared的标准库函数返回一个unique_ptr,当我们定义unique_ptr时,需要将其绑定到一个new返回的指针上。
  unique_ptr<double> p1; 
  unique_ptr<int> p2(new int(1024));
  cout<<*p2<<endl; // 1024  
  • 由于unique_ptr 拥有它指向的对象,因此unique_ptr 不支持普通的拷贝或赋值操作
  unique_ptr<string> p1(new string("Stegosaurus"));
//  unique_ptr<string> p2(p1); // 错误: unique_ptr 不支持拷贝
//    unique_ptr<string> p3;
//  p3 = p1; // 错误: unique_ptr 不支持赋值
  // 将所有权从p1 转移到 p2
  /*             
   *u.release() u放弃对指针的控制权,返回指针,并将U置空
   * 调用release()会切断unique_ptr 和他原来管理的对象间的联系,
   * release返回的指针通常被用来初始化另一个智能指针赋值。                                                               
   */ 
  unique_ptr<string> p2(p1.release());  // p1置为空
  unique_ptr<string> p3(new string("Text"));
  // 将所有权从p3 转移给 p2
  p2.reset(p3.release());
  cout<<*p2<<endl; // Test

weak_ptr

  • weak_ptr 是一种不控制所指向对象生存期的职能指针,它指向由一个shared_ptr管理的对象.
  • 将一个weak_ptr 绑定到一个shared_ptr 不会改变shared_ptr的引用计数。
  • 一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr 指向对象也会被释放。所以叫做 弱 只能指针
    auto p = make_shared<int>(42);
    weak_ptr<int> wp(p); // wp 弱共享p, p的引用计数未改变
    /*
     *由于对象可能不存在,我们不能使用weak_ptr 直接访问对象,而必须调用lock,
     * lock函数检查weak_ptr 指向的对象是否仍存在,如果存在,lock 返回一个指向共享对象
     * 的shared_ptr 
     */
    if(shared_ptr<int> np = wp.lock()) // 如果存在则进入该空间
    {
        cout<<*np<<endl;
    }

智能指针和动态数组

    // unique_ptr
    // up 指向一个包含0个为初始化 int的数组
    unique_ptr<int[]> up(new int[10]);
    // 指向数组的unique_ptr 不支持成员访问运算符 (点和箭头运算符)
    up.release(); // 自动用delete[] 销毁其指针
    int i;
    for (i=0;i<10;++i)
    { 
     up[i] = i;   
    } 

    // shared_ptr
    // shared_ptr 不支持管理动态数组,如果希望管理一个动态数组,必须提供自己定义的删除器
    shared_ptr<int> sp(new int[10],[](int *p){delete[] p;});
    sp.reset(); // 使用我们自定义的lambda 释放数组
    for (i=0;i<10;++i)
    {
     *(sp.get()+i) = i;                                                                                                    
    }

posted on 2021-08-30 16:03  lodger47  阅读(41)  评论(0)    收藏  举报

导航