C++基础回顾4——智能指针shared_ptr

———-引入智能指针的目的,个人;理解有如下两点:
1.自动释放内存:智能指针类能记录多少个shared_ptr指向相同的对象,并在引用计数值为0时自动释放对象所占用的内存。
2.内存共享:让多个对象共享底层数据。

C++动态内存(malloc & free, new & delete)

程序使用动态内存出于以下三种原因之一:

  • 程序不知道自己需要使用多少对象
  • 程序不知道所需对象的准确类型
  • 程序需要在多个对象间共享数据
vector<string> v1;

    {//新作用域
        string str[] = {"a", "an", "the"};
        int size = sizeof(str) / sizeof(str[0]);
        vector<string> v2(str, str + size);
        v1 = v2;
    }//v2被销毁,v1中包含三个元素

当拷贝一份vector时,原vector和副本vector中元素是相互分离的。
一般而言,如果两个对象共享底层的数据,当某个对象被销毁时,我们不能当方面的销毁底层数据。

Blob<string> b1;

    {//新作用域
        Blob<string> b2 = {"a", "an", "the"};
        b1 = b2;//b1和b2共享相同的元素
    }

对象b1与b2具有引用相同的底层元素。
实现Blob类如下:

class strBlob
{
public:
    typedef std::vector<string>::size_type size_type;
    strBlob();
    strBlob(initializer_list<string> i1);
    size_type size() const { return data->size(); };
    bool empty() const{ return data->empty(); };

    //添加和删除元素
    void push_back(const string &t) {data->push_back(t); };
    void pop_back();

private:
    shared_ptr<vector<string>> data;
    void check(size_type i, const string &msg) const;

}

shared_ptr与new的结合使用
默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象。

 shared_ptr<string> clone(int p)
 {
 //必须显示地调用int *创建shared_ptr<int>
     return shared_ptr<int>(new int(p));
 }

不要混合使用普通指针和智能指针

 void  process(shared_ptr<int> ptr)
 {
 //使用ptr

 }//ptr离开作用域,被销毁

process采用传值方式传递形参,因此实参会被拷贝给一个临时变量ptr,拷贝实参会递增引用计数。

 shared_ptr<int> p(new int(42));//引用计数为1;
 process(p); //引用计数为2,执行完process后引用计数变为1
 int i = *p;//p的引用计数为1;

智能指针删除器

struct destination;
struct connection;
connection connect(destination *d);
void disconnection(connection);

void f(destination *dd)
{
    connection conn = connect(dd);

    //使用完conn后并未及时关闭,需要单独调用disconnection
}

以上代码中若connection存在析构函数,还可以在析构函数中调用disconnect。但是不存在析构函数,就可以使用shared_ptr,与采用shared_ptr自动会调用delete避免内存泄漏的原理是一样的。
修改如下:

void end_connection(destionation *d){ disconnect(p); };
void f(destination *dd)
{
    connection conn = connect(dd);
    shared_ptr<connection> p(&conn, end_connection);
}

unique_ptr

某一时刻只能有一个unique_ptr指向一个给定对象,unique_ptr与对象是一一对应的关系。
    unique_ptr<string> p1(new string("Stegosaurus"));
    unique_ptr<string> p2(p1); //错误:unique_ptr不支持拷贝,unique_ptr没有对应的拷贝构造函数
    unique_ptr<string> p3;
    p3 = p2; //错误:unique_ptr不支持拷贝,unique_ptr没有对应的拷贝构造函数

unique_ptr操作

  • unique_ptr〈T〉 u1:空unique_ptr,可以指向类型为T的对象;u1会使用delete来释放它的指针。
  • unique_ptr〈T, D〉 u2:u2会使用一个类型为D的可调用对象来释放它的指针。
  • unique_ptr〈T, D〉 u(d)
  • u = nullptr
  • u.release() :u放弃对指针的控制权,返回指针,并将u置为空
  • u.reset():释放u指向的对象
  • u.reset(q):如果提供了内置q,令u指向这个对象;否则将u置位空。
    指向release之后,unique_ptr会切断与之前指向对象的联系,并返回当初指向的对象,这时就需要使用返回的对象初始化另一个智能指针。
p2.release();//错误:p2不会释放内存,而且我们丢失了指针
auto p = p2.release(); //正确,用完后必须delete(p)

weak_ptr操作
weak_ptr是一种不控制所指向对象生命周期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到shared_ptr上不会改变shared_ptr的引用计数。

  • weak_ptr〈T〉w:指向类型为T的空weak_ptr
  • weak_ptr〈T〉w(sp):与shared_ptr sp指向相同对象的weak_ptr,但是T必须能转换为sp可以指向的类型
  • w.reset()
  • w.use_count();
  • w.expired();
  • w = p
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值