美文网首页
C++智能指针

C++智能指针

作者: VictorHong | 来源:发表于2020-09-10 19:29 被阅读0次

unique_ptr

std::unique_ptr 是通过指针占有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象的智能指针。在下列两者之一发生时用关联的删除器释放对象:

  • 销毁了管理的 unique_ptr 对象
  • 通过 operator=reset() 赋值另一指针给管理的 unique_ptr 对象。

shared_ptr

std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象。下列情况之一出现时销毁对象并解分配其内存:

  • 最后剩下的占有对象的 shared_ptr 被销毁;
  • 最后剩下的占有对象的 shared_ptr 被通过 operator=reset() 赋值为另一指针。

每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,引用计数加1;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

shared_ptr的内存模型:

内存模型

下面是用类模板简单实现shared_ptr.

#include <iostream>
using namespace std;
 
template<typename T>
class SmartPointer {
private:
    T* p_;
    size_t* count_;
public:
    SmartPointer(T* ptr = nullptr) : p_(ptr) {
        if (p_) {
            count_ = new size_t(1);
        }
        else {
            count_ = new size_t(0);
        }
    }
 
    SmartPointer(const SmartPointer& ptr) {
        p_ = ptr.p_;
        count_ = ptr.count_;
        (*count_)++;
    }
 
    SmartPointer& operator=(const SmartPointer& ptr) {
        if (p_ == ptr.p_) {
            return *this;
        }
 
        if (p_) {
            if (--(*count_) == 0) {
                delete p_;
                delete count_;
            }
        }
 
        p_ = ptr.p_;
        count_ = ptr.count_;
        (*count_)++;
        return *this;
    }
 
    ~SmartPointer() {
        if (--(*count_) == 0) {
            delete p_;
            delete count_;
        }
    }
 
    size_t use_count() {
        return *count_;
    }
};
 
int main() {
    SmartPointer<int> sp1(new int(10));
    SmartPointer<int> sp2(sp1);
    SmartPointer<int> sp3(new int(20));
    sp2 = sp3;
    std::cout << sp1.use_count() << std::endl;
    std::cout << sp3.use_count() << std::endl;
}

智能指针带来的性能影响:

1)shared_ptr的尺寸是裸指针的两倍。

2)会带来控制块的开销。

3)引用计数的递增和递减是原子操作,原子操作一般都比非原子操作慢。

weak_ptr

weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的 shared_ptr. weak_ptr只是提供了对管理对象的一个访问手段。weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr

#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class B;
class A
{
public:
    weak_ptr<B> pb_;
    ~A()
    {
        cout << "A delete\n";
    }
};
class B
{
public:
    shared_ptr<A> pa_;
    ~B()
    {
        cout << "B delete\n";
    }
};

void fun()
{
    shared_ptr<B> pb(new B());
    shared_ptr<A> pa(new A());
    pb->pa_ = pa;
    pa->pb_ = pb;
    cout << pb.use_count() << endl;
    cout << pa.use_count() << endl;
}

int main()
{
    fun();
    return 0;
}

注意的是我们不能通过weak_ptr直接访问对象的方法,比如B对象中有一个方法print(),我们不能这样访问,pa->pb_->print(); 英文pb_是一个weak_ptr,应该先把它转化为shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();


参考:

  1. C++11--智能指针详解及实现

相关文章

网友评论

      本文标题:C++智能指针

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