智能指针介绍

一、智能指针的作用:

在C++中,动态内存的管理是用一对运算符完成的:new和delete,new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。

 

动态内存管理经常会出现三种问题:

1、申请之后忘记释放内存,会造成内存泄漏;

2、另一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。

3、还有一种是内存的二次释放,即对同一个指针进行两次 free() 操作,可能导致程序崩溃

 

智能指针的作用就是解决上述三种可能出现的问题,指针指针的使用效率不会比一般的指针高,但是它胜在更安全、更稳定

 

二、智能指针的本质

 

智能指针的实质是一个类对象,它是利用模板类对一般的指针进行封装,在类内的构造函数实现对指针的初始化,并在析构函数里编写delete语句删除指针指向的内存空间。这样在程序过期的时候,对象会被删除,内存会被释放,实现指针的安全使用。

 

三、智能指针的类型和使用

 

智能指针是在C++11版本之后提供,包含在头文件#include<memory>中,智能指针有四种类型,分别是shared_ptr、unique_ptr、auto_ptr、weak_ptr,这里只介绍前两种

 

每种指针都有不同的使用范围,unique_ptr指针优于其它两种类型,除非对象需要共享时用shared_ptr。

如果你没有打算在多个线程之间来共享资源的话,那么就请使用unique_ptr。

 

1、shared_ptr

 

shared_ptr可以将多个指针指向相同的对象(共享)。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,对象的引用计数

加1,每析构一次,对象的引用计数减1,减为0时,自动删除所指向的堆内存。

shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

 

shared_ptr的初始化

智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一

个是类,一个是指针。例如std::shared_ptr<int> p4 = new int(1);的写法是错误的

 

shared_ptr的拷贝和赋值

拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象。

  shared_ptr传参的过程就是内存的拷贝,使得对象的引用计数增加1

  

#include <iostream>
#include <memory>
using namespace std;
shared_ptr<int> func(shared_ptr<int> ps)
{
    (*ps)++;
    cout<<"ps.use_count()="<<ps.use_count()<<endl;
    return ps;
}
int main() {
    int n=100;
    //赋值
    shared_ptr<int>p=make_shared<int>(n);
    //拷贝
    shared_ptr<int>q (p);
    cout<<"q.use_count()="<<q.use_count()<<endl;
    cout<<"p.use_count()="<<p.use_count()<<endl;
    //传参
    p=func(p);
    cout<<"p=.use_count()"<<p.use_count()<<endl;
    cout<<*p<<endl;
}

 

 

 

 

get函数获取原始指针

我们前面说过,shared_ptr的本质是一个模板类,这里通过get()函数可以获取它的原始指针

 

 //创建共享指针同时赋值     ClassA是一个类
shared_ptr<ClassA> b = make_shared<ClassA>(100);
//b是一个类,c是类指针
ClassA* c=b.get()

 

 

 

注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存

 

2、unique_ptr

unique_ptr"唯一"拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)

 

unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作

符,用户可指定其他操作)。

 

unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、

通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

 

#include <iostream>
#include <memory>

int main() {
    {
        int a = 10;
        //动态绑定对象
        std::unique_ptr<int> p (new int(a));
        std::cout<<*p<<std::endl;
        
        //move转移所有权,转移之后指针p就变得无效了
        std::unique_ptr<int> q=std::move(p);
        std::cout<<*q<<std::endl;
      
        //release释放所有权,释放之后指针q变的无效
        q.release();
    }
}

 

 

 

 

上一篇:SQL_server——索引


下一篇:动态内存与智能指针