智能指针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

相关文章

全面解析Golang 中的 Gorilla CORS 中间件正确用法

《全面解析Golang中的GorillaCORS中间件正确用法》Golang中使用gorilla/mux路由器配合rs/cors中间件库可以优雅地解决这个问题,然而,很多人刚开始使用时会遇到配... 目录如何让 golang 中的 Gorilla CORS 中间件正确工作一、基础依赖二、错误用法(很多人一开

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

Java Spring的依赖注入理解及@Autowired用法示例详解

《JavaSpring的依赖注入理解及@Autowired用法示例详解》文章介绍了Spring依赖注入(DI)的概念、三种实现方式(构造器、Setter、字段注入),区分了@Autowired(注入... 目录一、什么是依赖注入(DI)?1. 定义2. 举个例子二、依赖注入的几种方式1. 构造器注入(Con

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

全面掌握 SQL 中的 DATEDIFF函数及用法最佳实践

《全面掌握SQL中的DATEDIFF函数及用法最佳实践》本文解析DATEDIFF在不同数据库中的差异,强调其边界计算原理,探讨应用场景及陷阱,推荐根据需求选择TIMESTAMPDIFF或inte... 目录1. 核心概念:DATEDIFF 究竟在计算什么?2. 主流数据库中的 DATEDIFF 实现2.1

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问