智能指针三剑客:shared_ptr的使用

目录

shared_ptr错误范例

其他补充

尺寸问题

移动语义


shared_ptr错误范例

裸指针:

#include<iostream>
using namespace std;
void Test(shared_ptr<int> ps)
{
    return;
}
int main()
{
    int *p=new int(666);
    Test(p);
//E0415	不存在从 "int *" 转换到 "std::shared_ptr<int>" 的适当构造函数	
//shared_ptr是禁止隐式类型转换的,有explicit属性
    Test(shared_ptr<int>(p));//临时shared_ptr对象
    *p=555;
//系统不报错,但是我们使用了已经被释放的内存。p在Test结束时就已经被智能指针释放。
    shared_ptr<int> pi1(p);
    shared_ptr<int> pi2(p);
//编译时报错,这样用裸指针初始化多个shared_ptr对象,pi1与pi2的引用计数并不关联。导致系统报错

}
//裸指针和智能指针混用会带来很多不引人注意的问题。如果使用裸指针给智能指针初始化,就不要再使用该裸指
//针了。更不要使用裸指针给多个shared_ptr对象初始化

get(): 

#include<iostream>
using namespace std;
int main()
{
    shared_ptr<int> ps(new int(666));
    int *p=ps.get();//这样获得的裸指针不要再delete。
    shared_ptr<int> ps2(p);
//这样也会导致ps与ps2的引用计数不相关联,系统异常。
}
//不要用get()得到的裸指针初始化shared_ptr对象

 将this指针作为shared_ptr对象返回:

#include<iostream>
using namespace std;
class CT
{
public:
    shared_ptr<CT> getself()
        {
            return shared_ptr<CT>(this);
        }
}
int main()
{
    shared_ptr<CT> ps1(new CT);
    shared_ptr<CT> ps2=ps1->getself();
//这样同样导致ps1与ps2的引用计数不关联,导致异常
//这时我们可以使CTpublic继承enable_shared_from_this(c++标准库中的模板类),
//再使用return enable_shared_from_this;代替return shared_ptr<CT>(this);
//就可以保证代码的正确了(其实是使用了weak_ptr的lock()功能)
}

 循环引用:

#include<iostream>
using namespace std;
class A
{
public:
    shared_Ptr<B> pb;
    ~A() {}
};
class B
{
public:
    shared_ptr<A> pa;
    ~B() {}
};
int main()
{
    shared_ptr<A> mpa(new A);
    shared_ptr<B> mpb(new B);
    mpa->pb=mpb;
    mpb->pa=mpa;
}//这样会造成死锁问题。mpa和mpb的析构函数都不会被释放,造成内存泄露。
//解决方案是将类中任意一个shared_ptr改为weak_ptr。

其他补充

尺寸问题

shared_ptr与weak_ptr对象占用的内存都是裸指针的两倍。例如shared_ptr是int *的两倍,也就是8字节。在这两倍的内存中,实际上包含两个裸指针。一个指向我们需要的对象,另一个指向控制块,控制块中包含着一些需要记录的内容,如强引用计数,弱引用计数,自定义的删除器,分配器等。当我们生成第一个指向某对象的shared_ptr对象时,控制块就会同时被分配出来。当我们用shared_ptr对象生成weak_ptr对象时,weak_ptr对象中的指针就会指向shared_ptr指向的对象,另一个指向该 shared_ptr对象指向的控制块,就是说,指向同一个对象的shared_ptr对象和weak_ptr对象指向同一个控制块。这也说明了weak_ptr的生成要依赖shared_ptr对象的原因,因为weak_ptr对象并不能自主生成控制块,必须提供shared_ptr对象给出供它指向的控制块。

移动语义

shared_ptr<int> p1=make_shared<int>(666);
shared_ptr<int> p2(std::move(p1));
//引用计数依旧为1,p1变为空

相比拷贝构造函数,移动构造函数的速度更快,且不增加引用计数。

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼多不菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值