智能指针std::auto_ptr和tr1:shared_ptr用法(总结的最好的一篇)

2024-09-01 23:32

本文主要是介绍智能指针std::auto_ptr和tr1:shared_ptr用法(总结的最好的一篇),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面通过一个工厂函数(createInvestment())返回一个特定的investment对象:

Investment* createInvestment();

 

见如下函数:

void f()

{

    Investment* pInv = createInvestment();

    ....

    delete pInv;

}

上面的程序会有以下危险:

1>...区域内的一个过早的return语句,控制流将不会触及delete语句

2>或createInvestment()和delete动作位于某循环内,该循环由于某个continue或goto语句过早退出.

3>...区域内的语句抛出异常,控制流也不会触及delete

无论delete如何被略过去,我们泄漏的不只是内含investment对象的那块内存,还包括那些investment对象所保存的任何资源.

 

为确保createInvestment()返回的资源总是被释放,我们需要将资源放进对象内,当控制流离开f,该对象的析构函数会自动释放那些资源,(RAII)如下:

void f()

{

    std::auto_ptr<Investment> pInv(createInvestment());

    ....

}

 

由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr同时指向同一对象,如果真是这样,对象会被删除一次以上,而那会使你的程序搭上驶向"未定义行为"的快速列车上,为了预防这个问题,auto_ptr有一个不同寻常的性质,若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权!如下:

std::auto_ptr<Investment> pInv1(createInvesment());//pInv1指向createInvesment()返回物

std::auto_ptr<Investment> pInv2(pInv1);            //现在pInv2指向对象,pInv1被设为null

pInv1 = pInv2;                                     //现在pInv1指向对象,pInv2被设为null

 

但是auto_ptr并非管理动态分配资源的神兵利器, STL容器要求其元素发挥"正常的"复制行为, 因此这些容器容不得auto_ptr

 

针对以上的问题auto_ptr的替代方案是RCSP,其也是个智能指针, RCSP提供类似垃圾回收行为,但其无法打破环状引用:TR1的tr1::shared_ptr就是个RCSP,可以如下写f函数:

void f()

{

   ...

   std::tr1::shared_ptr<Investment> pInv(createInvesment());

   ...

}

上段代码看起来与auto_ptr的那个版本相同,但他的复制行为就正常多了,如下:

void f()

{

   ...

   std::tr1::shared_ptr<Investment> pInv1(createInvestment());//pInv1指向createInvesment返回物

   std::tr1::shared_ptr<Investment> pInv2(pInv1);             //pInv1和pInv2指向同一个对象

   pInv1 = pInv2;                                             //同上

   ...                            //pInv1和pInv2被销毁,它们所指的对象也就被自动销毁

}

 

由于tr1::shared_ptr的复制行为"一如预期",它们可被利用于STL容器以及其它的"auto_ptr之非正统复制行为并不适用"的语镜上,以上即使使用了智能指针,最佳仍需要对createInvestment进行接口修改.

 

总结如下:

1>为防止资源,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源

2>两个经常被使用的RAII类分别是tr1::shared_ptr和auto_ptr,前者通常是较佳选择,因为其copy行为比较直观,若选择auto_ptr,复制动作会使被复制物指向null

这篇关于智能指针std::auto_ptr和tr1:shared_ptr用法(总结的最好的一篇)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128359

相关文章

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO

《一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO》在java编程中我们常常需要做数据交换,那么在数据交换过程中就需要使用到实体对象,这就不可避免的使用到vo、dto、po等实体对象,这篇... 目录深入浅出讲解各层对象区别+实战应用+代码对比,告别概念混淆,设计出更优雅的系统架构!一、 为什么

C# List.Sort四种重载总结

《C#List.Sort四种重载总结》本文详细分析了C#中List.Sort()方法的四种重载形式及其实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录1. Sort方法的四种重载2. 具体使用- List.Sort();- IComparable

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻

SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)

《SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)》本文总结了SpringBoot项目整合Kafka启动失败的常见错误,包括Kafka服务器连接问题、序列化配置错误、依赖配置问题、... 目录一、Kafka服务器连接问题1. Kafka服务器无法连接2. 开发环境与生产环境网络不通二、序

C++ scoped_ptr 和 unique_ptr对比分析

《C++scoped_ptr和unique_ptr对比分析》本文介绍了C++中的`scoped_ptr`和`unique_ptr`,详细比较了它们的特性、使用场景以及现代C++推荐的使用`uni... 目录1. scoped_ptr基本特性主要特点2. unique_ptr基本用法3. 主要区别对比4. u

Java序列化之serialVersionUID的用法解读

《Java序列化之serialVersionUID的用法解读》Java序列化之serialVersionUID:本文介绍了Java对象的序列化和反序列化过程,强调了serialVersionUID的作... 目录JavChina编程a序列化之serialVersionUID什么是序列化为什么要序列化serialV

python3中正则表达式处理函数用法总结

《python3中正则表达式处理函数用法总结》Python中的正则表达式是一个强大的文本处理工具,用于匹配、查找、替换等操作,在Python中正则表达式的操作主要通过内置的re模块来实现,这篇文章主要... 目录前言re.match函数re.search方法re.match 与 re.search的区别检索

MySQL 中的 JSON_CONTAIN用法示例详解

《MySQL中的JSON_CONTAIN用法示例详解》JSON_CONTAINS函数用于检查一个JSON文档中是否包含另一个JSON文档,这篇文章给大家介绍JSON_CONTAINS的用法、语法、... 目录深入了解 mysql 中的 jsON_CONTAINS1. JSON_CONTAINS 函数的概述2

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,