boost库学习:智能指针

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guangyacyb/article/details/85328648

scoped_ptr 

也叫作用域指针,一个指针独占一个动态分配的对象。对应的类名为 boost::scoped_ptr,它的定义在 boost/scoped_ptr.hpp 中。

与 std::auto_ptr 区别:不能将所指对象的所有权转移到另一个scoped_ptr。离开定义指针的作用域后,指针所指动态对象的空间将会释放。

源码

boost_1_69_0\boost\smart_ptr\scoped_ptr.hpp

主要有reset 和 swap 方法

简单使用

#include <iostream>
#include <boost/scoped_ptr.hpp>
using namespace std;

class A
{
  public:
    A(const int num) : val(num) {}
    ~A()
    {
      cout << "A destroy" << endl;
    }

    int val;
};

int main()
{                                                                                                                            
  boost::scoped_ptr<A> ptr1(new A(10));
  boost::scoped_ptr<A> ptr2(new A(5));

  cout << ptr1->val <<endl;
  cout << ptr2->val <<endl;
  // swap
  ptr1.swap(ptr2);
  cout << ptr1->val <<endl;
  cout << ptr2->val <<endl;

  //ptr1 = ptr2; // 编译不过
  //ptr1.reset(ptr1.get()); // 执行出错 Assertion `p == 0 || p != px'
  //ptr1.reset(ptr2.get()); // 输出三个 "A destroy"(原因参见reset实现)  但是此时ptr1 和 ptr2 指向相同的地址,释放两次导致出错
  ptr1.reset(new A(11)); // 执行成功,输出三个 "A destroy"


  return 0;
}


scoped_array

作用域数组,与scoped_ptr 相似。 不同在于,作用域数组的析构函数使用 delete[] 操作符来释放所包含的对象,所以针对的是丛台分配的数组对象。

源码

boost_1_69_0\boost\smart_ptr\scoped_array.hpp

简单使用

#include <iostream>
#include <boost/scoped_array.hpp>
using namespace std;

class A
{
  public:
    A() : val(0) {}
    ~A()
    {
      cout << "A destroy" << endl;
    }

    int val;
};

int main()
{
  boost::scoped_array<A> ptr1(new A[2]);
  ptr1[0].val = 1;
  (ptr1.get() + 1)->val = 2;
  //(ptr1.get() + 5)->val = 2; // 貌似不会报错  

  for (int i = 0; i < 2; i ++)
  {
    cout << (ptr1.get() + i)->val <<endl;
  }

  return 0;
}

shared_ptr

共享指针

基本与scoped_ptr 相同,不同在于不需独占一个对象,可以与其他shared_ptr 共同指向同一个对象,只有最后一个指向该对象的shared_ptr 销毁后,对象的空间才会被释放。

源码

boost_1_69_0\boost\smart_ptr\shared_ptr.hpp

简单使用

#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;

class A
{
  public:
    A(const int num) : val(num) {}
    ~A()
    {
      cout << "A destroy" << endl;
    }

    int val;
};

int main()
{
  boost::shared_ptr<A> ptr1(new A(5));
  boost::shared_ptr<A> ptr2(ptr1);
  cout << ptr1->val << endl;
  cout << ptr2->val << endl;
  ptr2.reset(new A(3));
  cout << ptr1->val << endl;
  cout << ptr2->val << endl;

  return 0;
}

输出:

5
5
5
3
A destroy
A destroy

shared_array

共享数组

类似于共享指针。 不同在于析构时默认使用 delete[] 操作符来释放所含的对象,相当于 scoped_array 和scoped_ptr的关系

源码

shared_array.hpp

简单使用

#include <iostream>
#include <boost/shared_array.hpp>
using namespace std;

class A
{
  public:
    A() : val(0) {}
    ~A()
    {
      cout << "A destroy" << endl;
    }

    int val;
};

int main()
{
  boost::shared_array<A> ptr1(new A[2]);
  boost::shared_array<A> ptr2(new A[3]);
  ptr1.get()->val = 1;
  ptr2[0].val = 2;
  ptr1.swap(ptr2);                      
  cout << ptr1[0].val << endl;
  cout << ptr2[0].val << endl;

  return 0;
}

输出:

2
1
A destroy
A destroy
A destroy
A destroy
A destroy

弱指针

不能独立使用,只有配合共享指针使用才有意义

weak_ptr 必须通过 shared_ptr 来初始化的。

主要方法:lock()

作用:返回另一个 shared_ptr,与用于初始化弱指针的shared_ptr共享所有权。 

weak_ptr 使用场景:当函数需要一个由共享指针所管理的对象,而这个对象的生存期又不依赖于这个函数时,就可以使用弱指针。 

源码

boost/weak_ptr.hpp

简单使用

#include <iostream>
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
using namespace std;

class A
{
  public:
    A(const int num) : val(num) {}
    ~A()
    {
      cout << "A destroy, num:" << val << endl;
    }

    int val;
};

int main()
{
  boost::shared_ptr<A> ptr0(new A(1));
  boost::weak_ptr<A> ptr1(ptr0);
  //ptr0.reset(); boost::shared_ptr<A> ptr2 = ptr1.lock(); // 这样执行顺序不会输出ptr2->val的值 
  boost::shared_ptr<A> ptr2 = ptr1.lock(); ptr0.reset(); // 这样执行顺序会输出ptr2->val的值

  if (ptr2)
  {
    cout << ptr2->val <<endl;
  }

  return 0;
}

以上代码,因为在ptr0释放之前,先用弱指针获得了一个共享指针,所以ptr0的reset并不会导致所指对象空间释放;要是改成注释掉的那句,那后面的ptr2->val 就不会输出。因为空间已经释放了。

介入式指针

intrusive_ptr 

与shared_ptr 工作方式近似,但是共享指针自己负责记录对象的引用次数,介入式指针需要程序员自己记录。

是一个侵入式的引用计数型指针,它可以用于以下两种情形:

1、对内存占用的要求非常严格,要求必须与原始指针一样;

2、现存代码已经有了引用计数机制管理的对象

源码

intrusive_ptr.hpp

简单使用

#include <iostream>                              
#include <boost/intrusive_ptr.hpp>
using namespace std;

class A {
    int count;
public:
    A() : count(0) {}

    virtual ~A()
    {
      cout << "A destroy" <<endl;
    }

    friend void intrusive_ptr_add_ref(A* p) {
        ++p->count;
    }

    friend void intrusive_ptr_release(A* p) {
        if (--p->count==0)
            delete p;
    }

    void add_ref() {
        ++count;
    }

    int release() {
        return --count;
    }

    int getCount()
    {
      return count;
    }

protected:
    A& operator=(const A&) {
        // 无操作
        return *this;
    }
private:
    // 禁止复制构造函数
    A(const A&);
};

int main(int argc, char* argv[])
{

    boost::intrusive_ptr<A> ptr0(new A());
    cout << ptr0->getCount() << endl;
    boost::intrusive_ptr<A> ptr1(ptr0);
    cout << ptr0->getCount() << endl;

    return 0;
}            

输出:

1
2
A destroy

指针容器

源码

boost/ptr_container/ptr_vector.hpp 

简单使用

有了以上的智能指针,将对象存储到容器里,可用以下写法一:

#include <boost/shared_ptr.hpp>
#include <vector>
#include <iostream>
#include <boost/ptr_container/ptr_vector.hpp>
using namespace std;

int main()
{
  // 写法一
  std::vector<boost::shared_ptr<int> > v;
  v.push_back(boost::shared_ptr<int>(new int(1)));
  v.push_back(boost::shared_ptr<int>(new int(2)));
  cout << *v[0].get() << endl;

  //写法二                                        
  boost::ptr_vector<int> v1;
  v1.push_back(new int(1));
  v1.push_back(new int(2));
  cout << *v[0] << endl;
}

第一种写法有以下问题:

1、反复声明 boost::shared_ptr 需要更多的输入

2、将 boost::shared_ptr 拷进、拷出,或者在容器内部做拷贝,需要频繁的增加或者减少内部引用计数,效率不高

Boost C++ 库提供了 指针容器 专门用来管理动态分配的对象,参考以上代码写法二。

boost::ptr_vector 专门用于动态分配的对象,它使用起来更容易也更高效。 但会独占它所包含的对象,因而容器之外的共享指针不能共享所有权,这跟 std::vector<boost::shared_ptr<int> > 相反。

专门用于管理动态分配对象的容器还包括:boost::ptr_deque, boost::ptr_list, boost::ptr_set, boost::ptr_map, boost::ptr_unordered_set 和 boost::ptr_unordered_map。这些容器等价于C++标准里提供的那些。最后两个容器对应于std::unordered_set 和 std::unordered_map

参考:

Boost C++ 库 第 2 章 智能指针

从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr 、shared_ptr 、weak_ptr 源码分析) 博主总结了很多Linux C 编程的内容

C++学习 boost学习之-intrusive_ptr

猜你喜欢

转载自blog.csdn.net/guangyacyb/article/details/85328648