Effective C++ 3.资源管理

news/2023/12/1 8:54:04 标签: c/c++

资源管理

条款13: 以对象管理资源

【Problem】

void f()
{ 
   Investment *pInv = createInvestment(); 
         ...  /* 这里存在诸多“不定因素”,造成 "delete pInv"得不到执行,存在内存泄露的可能。*/
   delete pInv;
} 

【Solution. 1】

使用auto_ptr智能指针确保资源的释放,避免内存泄露

void f(){ 
   std::auto_ptr<Investment> pInv(createInvestment()); 
   ...   
   /*函数退出之前,经由auto_ptr的析构函数自动删除pInv指针*/
}        

【Key Points】

“以对象管理资源”的两个关键想法:
1. 获得资源后立刻放进管理对象内(如auto_ptr)
2. 管理对象运用析构函数确保资源被释放

【Attention】

auto_ptr的限制,举例:

std::auto_ptr<Investment> 
    pInv1(createInvestment()); //pInv1指向createInvestment()返回值;
std::auto_ptr<Investment> 
    pInv2(pInv1);              //pInv2指向对象,而pInv1被设为NULL;
pInv1 = pInv2;                 //pInv1指向对象,而pIn2被设为NULL;

受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它。
STL容器要求其元素发挥正常的复制行为,因此这些容器容不得auto_ptr。

【Solution.2】

使用share_ptr智能指针(引用计数型智慧指针)

void f()
{ 
    ... 
    std::tr1::shared_ptr<Investment>  
        pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
    std::tr1::shared_ptr<Investment>  
        pInv2(pInv1); //pInv1,pInv2指向同一个对象;
    pInv1 = pInv2;    //同上,无变化
    ... 
}    //函数退出,pInv1,pInv2被销毁,它们所指的对象也竟被自动释放。

【Attention】
1. auto_ptr和tr1::share_ptr 两者都是在其析构函数内做delete而不是delete[];意味着在动态分配的array身上使用两者是个坏主意。

2. share_ptr不能管理循环引用的对象,否则造成内存泄露,举例:

class parent;
class child;

typedef boost::shared_ptr<parent> parent_ptr;
typedef boost::shared_ptr<child> child_ptr;

class parent
{
public:
    children_ptr child;
    ~parent() { std::cout <<"destruct parent."<<std::endl; }
};

class child
{
public:
    parent_ptr parent;
    ~child() { std::cout <<"destruct child."<<std::endl; }
};

int main(){
    parent_ptr pat(new parent()); //(pat 计数 = 1)
    children_ptr chd(new child()); //(chd 计数 = 1)
    pat->child = chd; //(chd 计数 = 2)
    chd->parent = pat; //(pat 计数 = 2)
    return 0; // (函数退出时,减一后仍然大于0,无法执行析构函数,造成内存泄露)
}

解决方法:
1. 当parent的生存期超过childr的生存期的时候,child内改为使用一个普通指针指向parent。
2. 使用弱引用的智能指针打破这种循环引用。举例:

暂略

条款14: 在资源管理类中小心coping行为

【Attention】

1. 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为
2. 普遍而常见的RAII类拷贝行为是:抑制拷贝,施行引用计数法。不过其它行为也可能被实现

【Solution】

“当一个RAII对象被复制,会发生什么事?”大多数时候你会选择一下两种可能:

1. 禁止复制。如果复制动作对RAII类并不合理,你便应该禁止之。利用条款6(禁止类的copying函数)。
2. 对底层资源使用”引用计数法“。有时候我们又希望保有资源,直到它的最后一个使用者被销毁。 利用shared_ptr
3. 转移底部资源的拥有权。 利用auto_ptr
4. 复制底部资源。 利用深拷贝
``

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

【Problem】
需要一个函数可将RAII对象(shared_ptr)转换为其所内含之原始资源.

【Solution】
有两种做法可以达成目标:
1. 显示转换
shared_ptr和auto_ptr提供一个get成员函数,用来执行显示转换,也就是返回智能指针内部的原始指针。
shared_ptr和auto_ptr重载指针取值操作符(operator->和operator*),它们允许隐式转换至底部原始指针。
(即在对智能指针对象实施->和*操作时,实际被转换为被封装的资源的指针。)

2. 隐式转换
隐式转换可能引起“非故意之类型转换”

RAII class 设计方式

class Font
{
public:
    ...
    FontHandle get() const//FontHandle是资源;显示转换函数
    {
        return f;
    }
    operator FontHandle() const//隐式转换这个值得注意,可能引起“非故意之类型转换”
    {
        return f;
    }
private:
    FontHandle f; // 资源
    ...
};

尽量使用显示转换,减少出错的可能

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

如果你在new表达式中使用[],必须在相应的delete表达式中也使用[]。
如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。

条款17:以独立语句将newed对象置入智能指针


http://www.niftyadmin.cn/n/1586344.html

相关文章

html5 右侧客服代码,js实现浮动在网页右侧的简洁QQ在线客服代码

本文实例讲述了js实现浮动在网页右侧的简洁QQ在线客服代码。分享给大家供大家参考。具体如下&#xff1a;这是一个简洁版的QQ在线客服&#xff0c;其实重要的是这个JS函数&#xff0c;只要有了这个JS函数&#xff0c;实际上你完全可以写一个这样的在线客服&#xff0c;它是用JS…

改号软件 android,谷歌聊天工具Hangouts升级:整合安卓手表

腾讯科技讯 在手机聊天工具热潮中&#xff0c;微博)Hangouts目前市场处境不佳。日前&#xff0c;Hangouts推出了全新的安卓客户端新版本4.0版&#xff0c;引入了安卓5.0中的Material Design设计语言&#xff0c;另外和安卓手表实现了深度整合。据PCWorld等美国科技新闻网站报道…

MyBatis入门学习教程-解决字段名与实体类属性名不相同的冲突

在平时的开发中&#xff0c;我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的&#xff0c;下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突。 一、准备演示需要使用的表和数据 CREATE TABLE orders(order_id INT PRIMARY KEY AUTO_INCREMEN…

android 三角形气泡,Android实现三角形气泡效果方式汇总

在开发过程中&#xff0c;我们可能会经常遇到这样的需求样式&#xff1a;这张图是截取京东消息通知的弹出框&#xff0c;我们可以看到右上方有个三角形的气泡效果&#xff0c;这只是其中一种&#xff0c;三角形的方向还可以是上、下、左、右。通过截图可以发现&#xff0c;气泡…

linux nginx中网页乱码

<meta charset"utf-8"/><html><head><meta charset"utf-8"/><title>转载于:https://blog.51cto.com/wsxxsl/1885635

网易新闻 html5,HTML5+SWIPER仿网易新闻横滑翻页及联动

【实例简介】一套仿网易新闻的闻横滑翻页&#xff0c;联动导航&#xff0c;用到了swiper.js zepto.js scroll.js效果不错【实例截图】【核心代码】swiper└── swiper├── css│ ├── app.css│ ├── idangerous.swiper.css│ ├── images│ │ ├── add-…

obs点歌插件 html效果,OBS歌曲显示插件使用图文教程

亲爱的葫芦丝们&#xff0c;大家好! (•̀ᴗ•́)و ̑̑响应群主大大的号召&#xff0c;小葫芦科技为广大的葫芦丝提供超级全面的各项插件教程。让萌新们远离困扰&#xff0c;小白们远离烦恼~闲话不多说&#xff0c;小编我开始讲解&#xff1a; (&#xff61;&#xff65;ω&a…

html怎么设置字段行数,如何在CSS网格布局中的列中填充项目

原标题&#xff1a;如何在CSS网格布局中的列中填充项目假设我们有n 个项目&#xff0c;并且我们必须在网格布局中将这些项目按列排序。列数是固定的&#xff0c;我们还必须确保网格布局中的行数最少&#xff0c;以便有效填充网格。在本文中&#xff0c;我把数字视为项目。并且根…

页面怎么导出html文件大小,报表HTML导出时自适应页面大小

第1章 概述默认情况下&#xff0c;报表在浏览器中是按实际大小显示的&#xff0c;所以当报表的大小超过浏览器的显示区域时&#xff0c;就会出现水平或垂直滚动条。这对于在Dashboard中展现的报表可能是一个问题。为避免出现滚动条&#xff0c;需要报表具备自动适应页面大小的能…

关于存量和增量的杂谈

关注存量&#xff0c;好处是稳定&#xff0c;但坏处时会被存量绑架。一个小区门口有一个煎饼摊&#xff0c;此时小区里的每日消费量是一个固定的存量&#xff0c;此时你在旁边也开了一个煎饼摊&#xff0c;这就是典型的存量的竞争&#xff0c;两个竞争对手提供同质化的产品&…

html+经典布局案例,HTML + CSS 经典布局(示例代码)

/*base-width 容器宽度 可以为 px 或 百分比*/base-width: 100%;/** fix-width-l 左侧固定宽度 可以为 px 或 百分比* fix-width-r 右侧固定宽度 可以为 px 或 百分比*/fix-width-l: 300px;fix-width-r: 300px;bg-color1: blue;bg-color2: red;bg-color3: green;.i-box{width:b…

Mac OS 使用 Vagrant 管理虚拟机(VirtualBox)

Vagrant&#xff08;官网、github&#xff09;是一款构建虚拟开发环境的工具&#xff0c;支持 Window&#xff0c;Linux&#xff0c;Mac OS&#xff0c;Vagrant 中的 Boxes 概念类似于 Docker&#xff08;实质是不同的&#xff09;&#xff0c;你可以把它看作是一个箱子&#x…

html table nei边框线,关于前端:原生js实现框选表格内容并批量更改vue

原生js实现框选表格内容并批量更改(vue)前言日常开发中&#xff0c;有这样的需要&#xff0c;须要在表格中进行框选&#xff0c;并对框选中的内容进行批量更改。源码于文章结尾demo上面链接供在线调试&#xff1a;https://codesandbox.io/s/tabl…解说次要思路通过监听鼠标事件…

git小技巧:git blame git show 查看某一行代码的修改历史

先查看某行代码由谁写的&#xff0c;在哪个commit中提交的&#xff1a;git blame file_name git blame -L 58,100 KeyboardActivity.java其显示格式为&#xff1a; commit ID | 代码提交作者 | 提交时间 | 代码位于文件中的行数 | 实际代码 类似于下面这样&#xff1a;这样&…

两台计算机怎么网络连接,两台电脑怎么连接局域网,详细教您两台电脑怎么连接局域网...

有用户提出两台电脑怎么连接局域网的问题&#xff0c;其实最简单的方法无疑是直接使用网线连接两台计算机&#xff0c;没有那么复杂的&#xff0c;那么两台电脑怎么连接局域网&#xff1f;下面&#xff0c;小编给大家带来了两台电脑连接局域网的图文。局域网在网络应用中比较常…

在生产环境中安全地运行Docker容器

在生产环境中&#xff0c;强化Docker容器的一种方法就是使它们不可变&#xff0c;也就是只读。安全地运行容器的其他方法还包括最小化受攻击面和应用Linux安全过程&#xff0c;标准Linux安全过程和针对容器环境的特定过程都要应用。\\在启动容器时传入--read-only标记就可以在只…
最新文章