C++中的智能指针最常用的是shared_ptr和unique_ptr,C++新手最常问的问题是我从一个函数中拿到unique_ptr,但要转成shared_ptr才能使用,要怎么转换?同理是否能将shared_ptr转换成unique_ptr?
我们先简单看看shared_ptr是什么。
std::shared_ptr<Widget> a = std::make_shared<Widget>();
这句代码会在栈中创建一个shared_ptr对象,其最基本的2个指针,一个指向在堆中创建的Widget对象,一个指向一个引用计数,方便后续记录有多少个shared_ptr引用了该Widget对象。
std::shared_ptr<Widget> a = std::make_shared<Widget>();
std::shared_ptr<Widget> b = a;
当指向了b = a的赋值语句后,内存的状态如下,也就是大家一起维护着Widget对象和引用计数,C++11对count还没有线程安全保护,新版C++对这块已经做了支持,这也意味着性能会有所下降。
unique_ptr的实现则要简单很多,他内部只维护了一个Ptr指针指向堆中的对象,并且不支持赋值等操作,只支持移动语义,也就是说有且只有一个指针能执行Widget
std::unique_ptr<Widget> a = std::make_unique<Widget>();
std::unique_ptr<Widget> b = std::move(a);
那我们看看相互转换的问题:
Q: unique_ptr转换成shared_ptr?
由于unique_ptr的语义是唯一拥有ownership,那只要对他执行move操作就能把ownership转移出去给shared_ptr
std::unique_ptr<Widget> a = std::make_unique<Widget>();
std::shared_ptr<Widget> b = std::move(a);
这样a就等价于nullptr,而b则指向了堆中的Widget对象,切count=1。
Q:shared_ptr转换成unique_ptr?
由于shared_ptr本质上是多人拥有ownership,所以要转换成语义更加严格的单人拥有ownership是做不到的,就像图2中a和b都指向了同一个对象,这种情况如果要转成一个unique_ptr c的话就需要同时清除掉a和b对于Widget的指向,这是很难做到的,所以标准里面不支持shared_ptr转成unique_ptr。
一句话总结这个原则,严格条件的ownership能转成宽松条件的ownership。
到此这篇关于如何理解shared_ptr和unique_ptr能否互转的文章就介绍到这了,更多相关hared_ptr和unique_ptr互转内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!