当前位置: 首页 > 编程日记 > 正文

Chapter12:动态内存

  • 智能指针——shared_ptr

为了更容易地使用动态内存,新的标准提供了智能指针来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放指向的对象。

智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。

1 if (p1 && p1->empty())

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数

make_shared<T>(args); //返回一个shared_ptr, 指向一个动态分配的类型为T的对象,使用args初始化此对象。

shared_ptr自动销毁所管理的对象,还会自动释放相关联的内存。

shared_ptr在无用之后仍然保留的一种可能是:你将shared_ptr存放在一个容器中,随后重排了容器,从而不在需要某些元素。这个时候你应该确保使用erase删除那些不再需要的shared_ptr的元素。

  • 使用了动态生存期的资源的类

(三种情况)

1. 程序不知道自己需要使用多少对象;例如容器类。

2. 程序不知道所需对象的准确类型;例如派生与继承。

3. 程序需要在多个对象间共享数据;到目前为止,我们使用过的类中,分配的资源都与对应对象生存期一致;但某些类分配的资源具有与原对象相独立的生存期,即:当某个对象被销毁时,我们不能单方面地销毁底层数据。

定义需要共享数据的类时,重点要考虑的是初始化、赋值、拷贝、销毁等拷贝控制得问题。

  • 直接管理内存:new/delete

初始化

默认情况下,动态分配的对象时默认初始化的,这意味着内置类型或组合类型的对象的值是未定义的,而类类型对象将用默认构造函数进行初始化;

对于定义了自己的构造函数的类类型来说,要求值初始化没有意义;不管采用什么形式,对象都会通过默认构造函数来初始化;

1 string *ps1 = new string; //默认初始化为空string
2 string *ps2 = new string(); //默认初始化为空string
3 
4 int* pi1 = new int;//默认初始化;*pi1的值未定义
5 int* pi1 = new int(); //值初始化为0

delete

释放一块并非new分配的内存,或者将相同的指针值释放多次,其行为是未定义的。

动态对象的生存期知道被释放时为止;

delete之后的指针值就变为无效了。虽然指针已经无效,但是很多机器上指针仍然保存着动态内存的地址。此时指针就变为空悬指针(dangling pointer),最好在delete之后将nullptr赋予指针。

动态内存的一个基本问题是:可能多个直着你指向相同的内存,而在实际系统中,查找相同内存的所有指针是异常困难的。

  • shared_ptr+new

接受指针参数的智能指针构造函数是explicit的,因此我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式。

1 shared_ptr<int> p1 = new int(1024);//错误,必须使用直接初始化形式
2 shared_ptr<int> p2(new int(1024));//正确,使用直接初始化形式

不要混合使用普通指针和智能指针——以防止同一块内存绑定到多个独立创建的shared_ptr上——推荐使用make_shared,而不是new。

 1 void process(shared_ptr<int> ptr)
 2 {//参数按值传递,发生拷贝操作
 3 }
 4 
 5 shared_ptr<int> p(new int(42));
 6 process(p);//在process中引用计数为2
 7 int i = *p;//引用计数为1
 8 
 9 int *x(new int(42));//x是普通指针
10 process(x);//错误
11 process(shared_ptr<int>(x));//会释放x的内存
12 int j = *x;

当将一个shared_ptr绑定到一个普通指针时,我们就将内存管理责任交给了这个shared_ptr。一旦这样做了,我们就不应该再使用内置指针来访问shared_ptr所指向的内存了;

使用一个内置指针来访问一个智能指针所负责的对象时很危险的,因为我们无法知道对象何时会被销毁。

不要使用get初始化另一个智能指针或为智能指针赋值——以防止同一块内存绑定到多个独立创建的shared_ptr上。

unique():在改变对象之前,我们要检查自己是否是当前对象的仅有的用户。如果不是,在改变之前,我们可能需要制作一份新的拷贝。

1 if (!p.unique())
2     p.reset(new string(*p));

智能指针使用规范

1. 不使用相同的内置指针值初始化(或reset)多个智能指针;

2. 不 delete get()返回的指针;

3. 不使用get()初始化或reset另一个智能指针;

4. 如果使用了get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变成无效了;

5. 如果你使用智能指针管理的资源不是new分配的内存,记住传递一个删除器给它。

  • 动态数组

标准库提供了一个可以管理new分配的数组的unique_ptr版本。为了用一个unique_ptr管理动态数组,我们必须在对象类型后面加一对空括号:

unique_ptr<int []> up(new int[10]>;
up.release();//自动用delete[]销毁其指针

与unique_ptr不同,shared_ptr不直接支持管理动态数组。如果希望使用shared_ptr管理动态数组,必须提供自己定义的删除器:

1 shared_ptr<int> sp(new int[10], [](int *p) {delete[] p; });
2 sp.reset();//使用lambda释放数组
1 for (size_t i = 0; i != 10; ++i)
2 {
3     up[i] = i;
4     *(sp.get() + i) = i;
5 }

  • allocator类

new有一些灵活性上的局限,其中一方面表现在它将内存分配和对象构造组合在一起。类似的,delete将对象析构和内存释放组合在一起;

当分配一大块内存时,我们通常计划在这块内存上按需构造对象。在此情况下,我们希望将内存分配和对象构造分离。这意味着我们可以分配大块内存,但只在真正需要时才执行对象创建工作。

allocator的两个伴随算法:

1 uninitialized_copy(b, e, b2);//从迭代器b和e指定的范围拷贝元素到迭代器b2指定的未构造的原始内存中。
2 uninitialized_copy_n(b, n, b2)
1 uninitialized_fill(b, e, t);//在迭代器b和e指定的原始内存范围内创建对象,值均为t的拷贝;
2 uninitialized_fill_n(b, n, t)

转载于:https://www.cnblogs.com/wangyanphp/p/5831109.html

相关文章:

判断JS对象是否拥有某属性两种方式

方式&#xff0c;但稍有区别 1&#xff0c;in 运算符 1 2 3 var obj {name:jack}; alert(name in obj); // --> true alert(toString in obj); // --> true 可看到无论是name&#xff0c;还是原形链上的toString&#xff0c;都能检测到返回true。 2&#xff0c;hasOwnP…

Linux之redhat7系统结构

一.linux系统结构 linux是一个倒树结构 linux中所有的东西都是文件 这些文件都在系统顶级目录“/” /就是根目录 /目录以下为二级目录这些目录都是系统装机时系统自动建立的 二级目录的作用 /bin ##二进制可执行文件也就是系统命令 /sbin ##系统管理命令存放位置 /boot …

ASP.NET优化

源地址&#xff1a;http://www.cnblogs.com/wangjingblogs/archive/2013/02/27/2934706.html http://jingyan.baidu.com/article/2d5afd69bfd0ff85a3e28e6d.html转载于:https://www.cnblogs.com/haizine/p/5841771.html

3D Touch介绍: 一个数字压力器App和Quick Actions

随着iPhone 6s and 6s Plus的发布&#xff0c;苹果介绍了全新的手机交互方式&#xff1a;重按手势。你应该知道&#xff0c;这个特性其实早已应用在苹果手表和MacBook产品中&#xff0c;名字叫Force Touch。它给用户交互添加了全新的维度&#xff01; 或许你对Force Touch为什么…

一些LUA函数(转载)

转自http://hi.baidu.com/chevallet/item/9a3a6410c20d929198ce3363 一些LUA函数 1、assert (v [, message])  功能&#xff1a;相当于C的断言&#xff0c;当表达式v为nil或false将触发错误,  message&#xff1a;发生错误时返回的信息&#xff0c;默认为"assertion f…

cifs------网络文件系统(1)

SMB文件共享 SMB&#xff08;Server Message Block&#xff09;通信协议是微软&#xff08;Microsoft&#xff09;和英特尔(Intel)在1987年制定的协议&#xff0c;主要是作为Microsoft网络的通讯协议。SMB 是在会话层&#xff08;session layer&#xff09;和表示层&#xff0…

Swift 教學:如何使用iOS Charts API 製作漂亮的圖表

在應付許多的資料時&#xff0c;比起只在表格中呈現&#xff0c;使用圖表來顯示資料&#xff0c;可以幫助使用者容易地了解資訊。有了圖表&#xff0c;相對於讀取整個資料表&#xff08;或幾個資料表&#xff09;你可以輕鬆地一眼便見到以圖形表示的資料&#xff0c;取得所需的…

在Proteus中添加标号

1.Proteus中添加组件后双击引脚可以快速生成一个最近的端口。 2.按A调出设置界面 3.在String中写&#xff1a;netH#,"H"可以换成自定义前缀。count为起始值&#xff0c;increment为增量。 4.依次点击想要编号的引脚。转载于:https://www.cnblogs.com/viaduct/p/58424…

九度OJ 1525 子串逆序打印 -- 2012年Google校园招聘笔试题目

题目地址&#xff1a;http://ac.jobdu.com/problem.php?pid1525 题目描述&#xff1a; 小明手中有很多字符串卡片&#xff0c;每个字符串中都包含有多个连续的空格&#xff0c;而且这些卡片在印刷的过程中将字符串的每个子串都打印反了&#xff0c;现在麻烦你帮小明将这些字符…

cifs------网络文件系统(2)

接着上篇博客继续&#xff1a; Samba 基本配置 [rootserver2 ~]# rpm -qc samba-common //查看smb的配置文件 1、黑、白名单的设定 默认白名单&#xff0c;设置的ip是黑名单用户&#xff1a;hosts deny ip 默认黑名单&#xff0c;设置的ip是白名单用户&#xff…

iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

原文地址&#xff1a;https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/02_Parse的网络缓存与离线存储/iOS网络缓存扫盲篇.md 目录 当我们在谈论缓存的时候&#xff0c;我们在谈论什么&#xff1f;GET网络请求缓存 80%的缓存需求&#xff1a;两行代码就可满足…

YARN集群维护部分问题汇总

云梯开发人员在云梯Yarn集群的搭建和维护过程中做了许多工作&#xff0c;本文选择这期间部分较为典型的问题&#xff0c;通过对这些问题的分析和解决方案&#xff0c;为大家分享分布式系统问题调查的经验。 调查的问题 1. 2013年初引入社区0.23时&#xff0c;调查ResourceManag…

linux系统管理及vim

1.管理输入输出 在linux系统中&#xff0c;正确输出的编号为1&#xff0c;错误输出编号为2 在系统中用普通用户执行 "student" find /etc -name passwd 因为student用户权限问题会有以下输出 find: ‘/etc/pki/CA/private’: Permission denied ##没有进入权力…

如何用 OS X 的 Xcode 写C语言程序

這篇是給新手看的。 如果你在 Windows 習慣使用 Visual C 或 Dev-C 的話&#xff0c;到了 Mac OS X 可能會突然不知道要怎麼寫程式&#xff0c;尤其當你已經用 Visual C 的 Debugger 用得很上手的話。 最近我們系上的課充滿了 C programming&#xff0c;我也稍微摸懂了 Xcode 的…

【转】初等数论 ——原根、指标及其应用

转自&#xff1a;http://blog.163.com/gc_chdch126/blog/static/172279052201641935828402/ 学习总结&#xff1a;初等数论&#xff08;3&#xff09;——原根、指标及其应用 2016-05-19 15:58:28| 分类&#xff1a; 信息学——学习总 | 标签&#xff1a;初等数论 数学 |…

互联网产品评论索引

这里收集一些评论文章&#xff0c;定期查看文章观点的正确性&#xff0c;索引持续更新中 网站前期如何获得推广资源 专访陶瑾&#xff1a;微信公众平台开发先行者转载于:https://www.cnblogs.com/needrunning/p/3000353.html

Apache服务器部署(1)

apache&#xff08;web服务器&#xff09;简介&#xff1a; Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;其跨平台和安全性被广泛使用&#xff0c;是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充&…

JavaScript关键字this指向

在js中this始终指向一个调用函数的那个对象 var a有种你干掉我啊; //纯粹调用函数 function test(){ console.log(this.a);//默认指向全局对象 } //test();//>windows.test() //作为对象的方法被调用 Function.prototype.logfunction(){ console.log(this.a); } //此时t为一…

项目开发过程中的收获与思考

2013年7月&#xff0c;我正式毕业了&#xff0c;到公司入职&#xff0c;也就正式成为了一名菜鸟程序员。到今天&#xff0c;2014年1月3日&#xff0c;目前主要的工作是公司一个项目中的一个功能模块&#xff0c;到我进入项目组算起&#xff0c;已经过了四个月了。因此&#xff…

【仿汽车之家】价格区间选择控件

仿照汽车之家iOS客户端“找车”栏目的价格区间选择控件&#xff0c;最终实现效果如下&#xff1a; 一、界面实现 *根据屏幕大小以及刻度的大小&#xff0c;宏定义需要用到的一些值 #define SCREENW [UIScreen mainScreen].bounds.size.width #define SCREENH [UIScreen mainScr…

Apache服务器部署(2)

签名CA证书 环境&#xff1a;server1:172.25.1.1 重置虚拟机 挂载yum源 [rootserver1 ~]# yum install mod_ssl -y //下载ssl模块 [rootserver1 ~]# yum install crypto-utils -y //安装加密软件 [rootserver1 ~]# genkey …

ASCII、Unicode、GBK和UTF-8字符编码的区别联系

一直对编码这块晕晕乎乎&#xff0c;今天终于看到一篇写的很清楚也很风趣的文章&#xff0c;转过来mark一下。 很久很久以前&#xff0c;有一群人&#xff0c;他们决定用8个可以开合的晶体管来组合成不同的状态&#xff0c;以表示世界上的万物。他们看到8个开关状态是好的&…

【iOS】快速集成轮播控件

自己写的一个轮播控件&#xff0c;初始化后只要实现两个数据源方法&#xff0c;几行代码就能快速集成&#xff0c;支持本地图片和网络图片&#xff0c;支持点击事件&#xff0c;可定制播放速度、指示器颜色/位置、默认加载图等&#xff0c;效果&#xff1a; 1.下载地址&#xf…

Hibernate中get方法和load方法的区别

一、get和load方法都是根据id去获得对应数据的&#xff0c;但是获得机制不同&#xff1a;如果使用get方法&#xff0c;hibernate会去确认该id对应的数据是否存在&#xff0c;它首先会去session中去查询(session缓存其实就hibernate的一级缓存)&#xff0c;如果没有&#xff0c;…

DNS高速缓存

DNS相关资料&#xff1a; 1.什么是DNS DNS&#xff08;Domain Name System域名系统&#xff09; 是互联网上存储域名和ip映射关系的一个分布式数据库&#xff0c;它负责把域名转换成ip地址&#xff0c;或ip地址转换为域名。DNS运行于TCP/UDP的53端口上。 2.什么是高速…

将时间改为显示:几天前,几小时前,或者几分钟前

&#xff08;原博客地址&#xff1a;http://blog.csdn.net/kenhins/article/details/38010811&#xff09; 方法一&#xff1a; 个人做法是保存时间戳&#xff0c;然后在前端用jq插件做转换&#xff0c;比如 smart-time-ago ----------------------------------------------- 方…

支持placeholder和自适配高度的TextView控件

一.应用于项目的效果如下&#xff1a; 二.使用方法&#xff1a; 1.导入JXTextView.h头文件 2.初始化,并添加到view中&#xff1a; JXTextView *textView [[JXTextView alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];textView.placeholder "请输入内容";tex…

ZOJ 3735 dp

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode3735 好久没做DP题了&#xff0c;一开始没理解题目里的C(M,3)是干什么&#xff0c;原来就是组合&#xff0c;C M 取3&#xff0c;就等于n*&#xff08;n-1&#xff09;*&#xff08;n-2&#xff09;/6;题目里还有…

haproxy实现高可用及负载均衡

Haproxy简介&#xff1a; Haproxy是一个使用c语言编写的自由开发源代码软件&#xff0c;它提供高可用性、负载均衡、以及基于http和tcp的应用程序代理。Haproxy特别使用于那些负载特别大的web站点。Haproxy运行在当前的硬件上&#xff0c;完全可以支持数以万计的并发连接&#…

Apache转发到Tomcat

#vi /etc/httpd/conf/httpd.conf 添加下面配置 NameVirtualHost *:80 <VirtualHost *:80>ProxyPreserveHost OnServerName www.域名.comProxyPass / http://www.域名.com:8080/system/ErrorLog logs/error_logCustomLog logs/access_log common</VirtualHost> 作者…