工程实践:到底要不要使用智能指针

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都可以用

如何选择智能指针

我们可以先看一下,俩种指针不好的地方。

  1. unique_ptr:调用者无法对提供的用户进行任何操作,因为unique_ptr是独占的。
    线程不安全。
  2. share_ptr:会付出额外的内存空间和引用计数的原子增量和减量。

结论:

  1. 大多数情况,都可以使用unique_ptr
  2. 使用shard_ptr的好处:有效地转移资源地所有权

注意不要踩的“坑”

  1. 一个裸指针,不要使用俩个shared_ptr管理。这样俩个shard_ptr引用计数都是1,一个释放了,另外一个就gg了。
  2. 使用shared_ptr作为函数的接口,如果有可能尽量用const_shared_ptr&的模式(这个我还没有感受)
  3. 智能指针的效率问题也是我们要考虑的问题,特别是share_ptr。

总结

其实绝大多数情况使用unique_ptr就够了,毕竟他就是代替裸指针的,咱之前用裸指针的时候,不也挺香的吗。

没有更完,暂时的经验就这些。

参考资料

Windows服务
C++智能指针unique_ptr详解
C++ 原始指针、shared_ptr、unique_ptr分别在什么场景下使用

以上是关于工程实践:到底要不要使用智能指针的主要内容,如果未能解决你的问题,请参考以下文章

到底要不要报考“通信工程”?

性能项目到底要不要调优

修正:C++编程经验:delete之后到底要不要置空?

C++编程经验:delete之后到底要不要置空?

C++编程经验:delete之后到底要不要置空?

作为一个前端开发到底要不要写测试?