C++的智能指针(初步学习)

C++的智能指针

Class: C++ClassByMyself
参考: The Cherno相关课程
内容不全,笔记自投。
智能指针实现了new与delete的很大一部分功能,说白了实现自动化了。

智能指针的实质是实现了原始指针的封装。

  • 智能指针本质上是原始指针的包装。当你创建一个智能指针,它会调用new并为你分配内存,然后基于你使用的智能指针,这些内存会在某一时刻自动释放。
  • 优先使用unique_ptr,其次考虑shared_ptr。

尽量使用unique_ptr因为它有一个较低的开销,但如果你需要在对象之间共享,不能使用unique_ptr的时候,就使用shared_ptr

unique_ptr

  • unique_ptr构造函数实际上是explicit的,没有构造函数的隐式转换,需要显式调用构造函数。
  • 最好使用std::unique_ptr<Entity> entity = std::make_unique<Entity>(); 因为如果构造函数碰巧抛出异常,不会得到一个没有引用的悬空指针从而造成内存泄露,它会稍微安全一些。
  • std::make_unique<>()是在C++14引入的,C++11不支持。
#include <iostream>
   #include <memory>

   class Entity
   {
   private:

   public:
    Entity()
    {
        std::cout << "Create!" << std::endl;
    }

    ~Entity()
    {
        std::cout << "Destroy!" << std::endl;
    }
       void Print(){}
   };

   int main()
   {
    {
           //使用unique_ptr的一种方式
        std::unique_ptr<Entity> entity = new Entity(); // error! unique_ptr不能隐式转换
        std::unique_ptr<Entity> entity(new Entity());//ok,可以但不建议
           std::unique_ptr<Entity> entity = std::make_unique<Entity>(); //推荐使用std::make_unique。因为如果构造函数碰巧抛出异常,它会稍微安全一些。std::make_unique<>()是在C++14引入的,C++11不支持。
           entity->Print();  //像一般原始指针使用

    }

    std::cin.get();
   }

share_ptr

  • 跟踪你的指针有多少个引用,一旦引用计数达到零,他就被删除了。

引用计数基本上是一种方法,可以跟踪你的指针有多少个引用,一旦引用计数达到零,他就被删除了。

例如:我创建了一个共享指针shared_ptr,我又创建了另一个shared_ptr来复制它,我的引用计数是2,第一个和第二个,共2个。当第一个死的时候,我的引用计数器现在减少1,然后当最后一个shared_ptr死了,我的引用计数回到零,内存就被释放。

  • shared_ptr需要分配另一块内存,叫做控制块,用来存储引用计数,如果您首先创建一个new Entity,然后将其传递给shared_ptr构造函数,它必须分配,做2次内存分配。先做一次new Entity的分配,然后是shared_ptr的控制内存块的分配。然而如果你用make_shared你能把它们组合起来,这样更有效率。

怎么说呢,这两次内存分配,第一次是实例化调用构造函数时做出的内存分配

第二次是,share_ptr本身特性造成的,它需要开辟一个存储计数的内存块

所以make_shared的组合出现了(C17),还是优先用吧!!!

std::shared_ptr<Entity> sharedEntity = sharedEntity(new Entity());//不推荐!
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();//ok
  • unique_ptr和shared_ptr的一个显著区别在于,前者唯一不可复制,后者的主要用处就在于复制!
int main()
{
    {
        std::shared_ptr<Entity> e0;//这里就算一个引用了
        {
        //  std::shared_ptr<Entity> sharedEntity = sharedEntity(new Entity());//不推荐!
            std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();//ok
            e0 = sharedEntity; //可以复制
        } //此时sharedEntity已经“死了”,但没有调用析构,因为e0仍然是活的,并且持有对该Entity的引用,此时计数由2-》1
    } //析构被调用,因为所有的引用都消失了,计数由2-》0,内存被释放

    std::cin.get();
}

弱指针weak_ptr (这玩意的使用主要看需求)

1.可以和共享指针shared_ptr一起使用。

2.weak_ptr可以被复制,但是同时不会增加额外的控制块来控制计数,仅仅声明这个指针还活着。

当你将一个shared_ptr赋值给另外一个shared_ptr,引用计数++,而若是

把一个shared_ptr赋值给一个weak_ptr时,它不会增加引用计数

{
    std**::**weak_ptr**<**Entity**>** e0;
    {
        std**::**shared_ptr**<**Entity**>** sharedEntity **=** std**::**make_shared**<**Entity**>**();
        e0 **=** sharedEntity;
    } *//此时,此析构被调用,内存被释放*
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值