热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

EffectiveC++随笔13to17资源管理

资源管理并不单指内存,这里的资源包括内存、文件描述器、互斥锁、图形界面中的字形与笔刷、数据库连接、网络sockets等,其中最常用的是内存资源。13.以对象管理资源为防止资源泄露的



资源管理并不单指内存,这里的资源包括内存、文件描述器、互斥锁、图形界面中的字形与笔刷、数据库连接、网络sockets等,其中最常用的是内存资源。


13.以对象管理资源

为防止资源泄露的一个简单方法是:使用RAII对象,(资源取得即初始化),通常在构造函数中分配资源,在析构函数中释放资源。这样做带来的好处是:对象在离开作用域时,会隐式调用析构函数,将内存释放,不必担心忘记将资源释放及提早return或出现异常导致资源未释放的问题。

RAII的一个例子是智能指针auto_ptr,智能指针的一个特点是:由于智能指针被销毁时会自动释放指向的内存,因此不允许两个指针指向同一块内存。在指针赋值时,ptr1=ptr2,ptr1接受ptr2的赋值后,ptr2会变成NULL,ptr1拥有该资源的唯一控制权,这一特性不同于普通指针。

若要完成两个指针指向同一内存的功能,可以使用shared_ptr,称为引用技术性智慧指针(RCSP),它追踪共有多少对象指向某笔资源,并在无人指向时释放该资源。

值得说明的一点是:使用智能指针完成动态分配数组是一个糟糕的想法,因为智能指针析构时调用的是delete而非delete[ ],这将只释放掉数组的头指针,而数组内存无法释放。若你有该需求,使用vector是个好的选择。


14.资源管理类中小心copy行为

复制RAII对象必须一并复制它所管理的资源,所以资源的copy行为决定了RAII对象的copy行为。当一个RAII对象被复制时,我们通常会考虑下面的策略:

(1)禁止复制

对于一些RAII对象,对其进行复制操作事实上并不合理(如互斥锁),此时我们应该禁止复制,实现方法之前有详述(重载复制构造函数设为private)。

(2)对底层资源使用“引用计数法”

有时候我们希望保留某资源,直至其最后一个调用者被销毁,类似于shared_ptr的机制。

这里的shared_ptr允许指定第二个参数,将一函数作为删除器,在调用者计数为零时,将会调用该删除器完成相应功能(本例中是解开互锁)



(3)复制底部资源

这要求复制时不仅复制资源管理对象,同时也复制其所包覆的资源。这种复制方式称为“深拷贝”。

(4)转移底部资源

auto_ptr是一个典型。


15.在资源管理类中提供对原始资源的访问

RAII给我们提供了一种管理内存的机制,但有时我们经常会遇到需要访问原始资源的问题,因此每一个RAII类应当提供一种访问其原始资源的方法如get()函数。对原始资源的访问可能经由显式转换或隐式转换,一般来说显式转换比较安全,但隐式转换对用户来说比较方便。

在这里插入图片描述

在这里插入图片描述


16.成对使用new和delete时要采取相同形式

delete与new一一匹配,delete[ ]与new一个数组一一匹配。

(来自C++ primer)

当new函数运行时,实际上发生三个步骤:

1.调用operator new的标准库函数,分配足够大的原始未类型化的内存,以保存指定类型的一个对象。

2.运行该类型的一个构造函数,使用指定初始化式构造对象

3.返回指向新分配并构造对象的指针

当delete函数运行时,实际上发生两个步骤:

1.对指针指向的对象调用适当的析构函数

2.调用operator delete的标准库函数释放对象使用的内存


17.以独立语句将newd对象置入智能指针

在这里插入图片描述

为什么上图的做法不是一个好的选择?

因为按需要本应按下图的顺序执行工作:

在这里插入图片描述

但C++并未定义其顺序,编译器完全可能以下面的顺序完成在这里插入图片描述

此时问题出现了,若第二步出现异常,则第三步不会运行,作为唯一能够控制该内存的智能指针并未建立,该块内存将永远不能被我们访问与释放。

因此我们应当将使用独立语句将其置入智能指针,以避免出现异常导致句柄丢失影响内存释放。

在这里插入图片描述



推荐阅读
  • 本文详细介绍了Objective-C中的面向对象编程概念,重点探讨了类的定义、方法的实现、对象的创建与销毁等内容,旨在帮助开发者更好地理解和应用Objective-C的面向对象特性。 ... [详细]
  • 解决Xcode PBXcp 错误:找不到文件或目录
    当在Xcode中遇到PBXcp错误提示'No such file or directory'时,通常是由于文件引用问题导致的。本文将介绍两种有效的方法来解决这一常见问题。 ... [详细]
  • 本文详细介绍了在 Windows 7 上安装和配置 PHP 5.4 的 Memcached 分布式缓存系统的方法,旨在减少数据库的频繁访问,提高应用程序的响应速度。 ... [详细]
  • 深入解析mt_allocator内存分配器(二):多线程与单线程场景下的实现
    本文详细介绍了mt_allocator内存分配器在多线程和单线程环境下的实现机制。该分配器以2的幂次方字节为单位分配内存,支持灵活的配置和高效的性能。文章分为内存池特性描述、内存池实现、单线程内存池实现、内存池策略类实现及多线程内存池实现等部分,深入探讨了内存池的初始化、内存分配与回收的具体实现。 ... [详细]
  • 如何处理PHP缺少扩展的问题
    本文将详细介绍如何解决PHP环境中缺少扩展的问题,包括检查当前环境、修改配置文件以及验证修改是否生效的具体步骤,帮助开发者更好地管理和使用PHP扩展。 ... [详细]
  • 本文面向非计算机专业背景的编程爱好者,介绍如何仅使用基础的C语言知识——二维数组和结构体,无需掌握复杂的数据结构如链表,即可编写一款经典的贪食蛇游戏。通过本教程,您将了解游戏开发的基本原理和实现方法。 ... [详细]
  • 本文详细介绍如何在Spring Boot项目中集成和使用JPA,涵盖JPA的基本概念、Spring Data JPA的功能以及具体的操作步骤,帮助开发者快速掌握这一强大的持久化技术。 ... [详细]
  • 本文通过两个具体案例——共同好友查找和线段重叠分析,展示了如何利用Scala编程语言解决实际问题。案例一探讨了如何在社交网络中找出两个用户之间的共同好友;案例二则深入解析了如何计算多条线段之间的重叠情况。 ... [详细]
  • J2EE平台集成了多种服务、API和协议,旨在支持基于Web的多层应用开发。本文将详细介绍J2EE平台中的13项关键技术规范,涵盖从数据库连接到事务处理等多个方面。 ... [详细]
  • 设计模式系列-原型模式
    一、上篇回顾上篇创建者模式中,我们主要讲述了创建者的几类实现方案,和创建者模式的应用的场景和特点,创建者模式适合创建复杂的对象,并且这些对象的每个组成部分的详细创建步骤可以是动态的变化的,但 ... [详细]
  • 使用 Docker 部署 MongoDB 并通过 IntelliJ IDEA 远程访问
    本文详细介绍了如何使用 Docker 部署 MongoDB,并通过 IntelliJ IDEA 实现远程连接的方法。包括 MongoDB 的基本配置、用户管理以及如何在 IDE 中配置连接。 ... [详细]
  • 本文提供了多个关键点来帮助开发者提高Java编程能力,包括代码规范、性能优化和最佳实践等方面,旨在指导读者成为更加优秀的Java程序员。 ... [详细]
  • 本文详细介绍了Golang中string类型的内部结构及其特性,包括字符串的定义、表示方式、数据结构以及相关的操作方法,如字符串拼接和类型转换等。 ... [详细]
  • 本文介绍了一个基本的同步Socket程序,演示了如何实现客户端与服务器之间的简单消息传递。此外,文章还概述了Socket的基本工作流程,并计划在未来探讨同步与异步Socket的区别。 ... [详细]
  • C#中实现高效UDP数据传输技术
    C#中实现高效UDP数据传输技术 ... [详细]
author-avatar
天蝎快乐公主_594
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有