工程实践:到底要不要使用智能指针
Posted CodeBowl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工程实践:到底要不要使用智能指针相关的知识,希望对你有一定的参考价值。
工程实践:到底要不要使用智能指针
前言
写了很久的“C with class”,在接触到智能指针的时候,都有点欣喜若狂了,想的是,这下子不用再为new/delete头疼了,也不用担心内存泄漏了,但事实证明我太天真了。
之前也学过modern cpp,甚至还总结过智能指针,但是看来没有实际的操作,空想还是太虚了!
本文仅作新手经验所记,必不全面
我最想探讨的问题就是什么时候该用智能指针,该用什么智能指针,有没有什么需要注意的地方。
从需求开始探讨问题
这个需求是我根据经验虚拟的。
class object
pulic:
int test =1;
bool get_object(object** p1)
object* p2=new object();
p2->test=3;
*p1=p2;
int main()
object * pobject;
get_object(&pobject);
delete pobject;
return 0;
我想把参数和局部变量里的裸指针都变成智能指针,免得我手残犯错,造成内存泄漏~
智能指针现状
auto_ptr: 跟98的前辈say goodbye,尽量不使用。
unique_ptr
独占指针:实际上是个对象,在对象的外面包围了一个拥有该对象的普通指针,被包围的指针,被称为裸指针。
当需要让单个指针拥有动态分配的对象时,可以使用独占指针。
对象的所有权可以从一个独占指针转移到另外一个独占指针。
其转移方式为:对象始终只能有一个指针作为其所有者。当独占指针离开其作用域或将要拥有不同的对象时,它会自动释放自己所管理的对象。
这个似乎满足我通过函数参数将对象传出的需求,因为我这个函数本身就是为了去获得对象,所以我可以在函数内将对象进行转移。
示例
不能直接通过值给函数传递一个智能指针,因为通过值传递将导致复制真正的形参。如果要让函数通过值接收一个独占指针,则在调用函数时,必须对真正的形参使用 move() 函数:
//函数使用通过值传递的形参
void fun(unique_ptr<int> uptrParam)
cout << *uptrParam << endl;
int main()
unique_ptr<int> uptr(new int);
*uptr = 10;
fun (move (uptr)); // 在调用中使用 move
当然,如果通过引用传递的方式,那就不必对真正的形参使用 move() 函数了。示例代码如下:
//返回指向动态分配资源的独占指针
unique_ptr<int> makeResource()
unique_ptr<int> uptrResult(new int);
*uptrResult = 55;
return uptrResult;
int main()
unique_ptr<int> uptr;
uptr = makeResource () ; // 自动移动
cout << *uptr << endl;
有趣的是,可以从函数中返回一个独占指针,这是因为在遇到返回 unique_ptr 对象的函数时,编译器会自动应用 move() 操作以返回其值。来看以下代码:
//返回指向动态分配资源的独占指针
unique_ptr<int> makeResource()
unique_ptr<int> uptrResult(new int);
*uptrResult = 55;
return uptrResult;
int main()
unique_ptr<int> uptr;
uptr = makeResource () ; // 自动移动
cout << *uptr << endl;
最后一种情况也满足我的需求,可以通过函数获得对象,通过返回值获得也是一种方法。
shard_ptr
这一块直接看这个链接,我认为写的不错:
shared_ptr使用场景、陷阱、性能分析,使用建议
为什么多线程读写 shared_ptr 要加锁?
共享指针
我这个人擅长模仿学习,看见别人的代码里用的都是shared_ptr,所以在一段时间里,我第一想法也是使用shared_ptr。
weak_ptr:
弱指针
配合share_ptr使用,避免出现循环引用
接口该不该使用智能指针
可以用,挺好的,但可能牺牲点额外的内存空间和性能。
智能指针作为函数参数
需要注意值传递和引用传递的问题,这个上面有体现。
智能指针作为函数返回值
可以的,返回值会自动move,shared_ptr和unique_ptr都可以用
如何选择智能指针
我们可以先看一下,俩种指针不好的地方。
- unique_ptr:调用者无法对提供的用户进行任何操作,因为unique_ptr是独占的。
线程不安全。 - share_ptr:会付出额外的内存空间和引用计数的原子增量和减量。
结论:
- 大多数情况,都可以使用unique_ptr
- 使用shard_ptr的好处:有效地转移资源地所有权
注意不要踩的“坑”
- 一个裸指针,不要使用俩个shared_ptr管理。这样俩个shard_ptr引用计数都是1,一个释放了,另外一个就gg了。
- 使用shared_ptr作为函数的接口,如果有可能尽量用const_shared_ptr&的模式(这个我还没有感受)
- 智能指针的效率问题也是我们要考虑的问题,特别是share_ptr。
总结
其实绝大多数情况使用unique_ptr就够了,毕竟他就是代替裸指针的,咱之前用裸指针的时候,不也挺香的吗。
没有更完,暂时的经验就这些。
参考资料
Windows服务
C++智能指针unique_ptr详解
C++ 原始指针、shared_ptr、unique_ptr分别在什么场景下使用
以上是关于工程实践:到底要不要使用智能指针的主要内容,如果未能解决你的问题,请参考以下文章