C++智能指针的使用

C++智能指针的使用

C++11中提供了三种智能指针(unique_ptr、shared_ptr、weak_ptr)来自动回收堆分配的对象。

unique_ptr

unique_ptr如它的名字所传达的意思,其所指向的内存区不能与unique_ptr定义的另一个指针共享。看代码比较容易理解。

#include <memory>
#include <iostream>
using namespce std;
int main(){
	unique_ptr<int> p1(new int(11));
	unique_ptr<int> p2 = p1;  //不能通过编译
}

p1为unique_ptr类型指针,其不能与p2共享同一片内存区域。
当然也可以用标准库的move函数显式的将“所有权”转移给另一个unique_ptr指针,但原来的指针名将不能再使用。

#include <memory>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
	unique_ptr<int> p1(new int(11));
	unique_ptr<int> p2 = move(p1);//用move函数进行“所有权”转移
    cout << *p1 << endl;//能编译通过,但运行时报Segmentation fault错误
    cout << *p2 << endl;
    p2.reset();//可以显式地进行内存释放。
    p2.reset();//多次释放也不会报错
}

可以看到“所有权”已经被转移走的p1已经不能用*来获取存储值了。另外需要注意的一点是,unique_ptr定义的指针可以不用自己来释放内存。但也可以自己显式地用reset释放内存,而且多次释放也不会报错。

shared_ptr

shared_ptr相对于unique_ptr来说最主要的区别是它可以共享指针,可以多个指针变量指向一片共同的存储区。

#include <memory>
#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
	shared_ptr<int> sp1(new int(11));
	shared_ptr<int> sp2 = sp1;//可以正常进行赋值
    cout << *sp1 << endl;//可以正常输出
    cout << *sp2 << endl;//可以正常输出
    sp1.reset();
    // sp2.reset();
    // cout << *sp1 << endl;
    cout << *sp2 << endl;
}

可以看到上面虽然用reset显式地释放了sp1指向的内存。但实际上并没有真正释放其指向的内存。因为sp2依然可以正常访问。可以想象,共享指针内部实现了一个计数,只有指向该内存空间的所有共享指针都进行了释放操作,该内存才真正释放。这避免了普通指针进行多次释放引发的错误。

weak_ptr

weak_ptr可以指向shared_ptr指针指向的对象内存,但并不拥有该内存。使用weak_ptr的lock成员函数可返回其指向内存的一个shared_ptr对象,且在所指对象已经无效时,返回指针空值(nullptr)。这在验证share_ptr智能指针的有效性上会很有作用。

#include <iostream>
#include <memory>
using namespace std;
void Check(weak_ptr<int> & wp)
{
    shared_ptr<int> sp = wp.lock(); //转换为shared_ptr<int>
    if(sp !=  nullptr)
    {
        cout << "still " << *sp << endl;
    }
    else
    {
        cout << "pointer is invalid." << endl;
    }
}
int main(int argc, char** argv)
{
	shared_ptr<int> sp1(new int(22));
	shared_ptr<int> sp2 = sp1;  
    weak_ptr<int> wp = sp1;//指向shared_ptr<int>所指的对象
    cout << *sp1 << endl;
    cout << *sp2 << endl;
    Check(wp); //still 22
    sp1.reset();
    cout << *sp2 << endl;
    Check(wp); //still 22
    sp2.reset();
    Check(wp);//pointer is invalid.
}

当对sp1和sp2都调用了reset函数。这样导致对唯一的堆内存对象的引用计数降至0。一旦引用计数变成0后,shared_ptr<int>就会释放堆内存空间,指针就会失效。此时再调用weak_ptr的lock函数时就会返回一个指针空值nullptr。而Check函数则会打印pointer is invalid.

关注公众号《首飞》回复“机器人”获取精心推荐的C/C++,Python,Docker,Qt,ROS1/2,机器人学等机器人行业常用技术资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

首飞爱玩机器人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值