###学习《C++ Primer》- 5
点击查看Evernote原文。
// @author: gr
// @date: 2014-10-20
// @email: forgerui@gmail.com
Part 5: 动态内存(第12章)
一、new初始化对象
使用new 对类类型和内置类型进行初始化会有不同的效果。对于类类型,不论采用何种形式,对象都会使用默认构造函数来初始化。直接初始化的内置类型对象值被良好定义,而默认初始化的对象的值是未定义的。
// 类型后没括号是默认初始化,有括号是直接初始化
string *ps1 = new string; //值初始为空string
string *ps2 = new string(); //值初始为空string
int *pi1 = new int; //值未定义
int *pi2 = new int(); //值初始为0
往往,对动态分配的对象进行直接初始化通常是个好主意。
可以使用auto来自动推断我们想要分配的类型。要求,括号中仅有单一初始化器时才可以使用auto。
// p指向一个与obj类型相同的对象,该对象用obj进行初始化
auto p1 = new auto(obj);
// 错误,括号中只能有一个初始化器
auto p2 = new auto{a, b, c};
p1的类型是一个指针,从obj自动推断出来。如果obj是一个int,那么p1就是个int*。
二、动态分配的const对象
由于分配的对象是const的,所以new返回的指针是一个指向const的指针。初始化规则和上面new初始化一样,如果是内置类型,则需要显示初始化。
const int* pi = new const int(1024); //显示初始化
const string* ps = new const string; //隐示初始化
三、内存耗尽
如果使用new无法分配所要求的空间,这时会抛出一个bad_alloc的异常。可以通过改变使用new的方式来阻止抛出异常:
int* pi1 = new int(1); //如果分配失败,抛出std::bad_alloc异常
int* pi2 = new (nothrow) int(1); //如果分配失败,new返回一个空指针,不抛出异常
这种new称为定位new,允许向new传递参数。在本例中,将nothrow传递给new。
bad_alloc和nothrow都在头文件new中,记着要#include <new>。
四、delete
delete工作:
- 销毁给定指针指向的对象
- 释放对应的内存
传递给delete的指针必须指向动态分配的内存,或是一个空指针。不能对同一块内存释放两次。
const对象虽然是不可改变的,但是可以销毁的,和其他的销毁一样,如下:
const int* pi = new const int(1);
delete pi;
在delete指针过后,要重置为nullptr。这样以后进行NULL检查才会有作用。
delete p;
p = nullptr;
但即使这样,也不能保证所有指针都置为nullptr。
int *p(new int(42));
auto q = p;
delete p;
p = nullptr;
虽然把p置为nullptr,q仍为无效的。
五、shared_ptr类
shared_ptr在头文件memory中。使用它,记着#include <memory>。
与vector类似,智能指针也是模板,在尖括号内给出类型。智能指针使用方式与普通方式类似,解引用一个智能指针返回它指向的对象。
shared_ptr<string> p1;
p1->empty(); // 调用成员函数
shared_ptr<vector<string> > pv;
使用make_shared函数,创建智能指针。
shared_ptr<int> p3 = make_shared<int>(42);
当指向一个对象的最后一个shared_ptr被销毁时,即引用计数为0时,shared_ptr类会自动销毁此对象。无需手动调用。
六、shared_ptr和new结合使用
如果不初始化智能指针,它就会被初始化为一个空指针。还可以用new返回的指针来初始化智能指针。只能使用显示转换,不能使用隐式转换:
shared_ptr<int> pi1 = new int(11); //错误,隐匿转换
shared_ptr<int> pi2(new int(11)); //正确,显示转换
七、unique_ptr
与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。它不支持普通的拷贝或赋值操作。
unique_ptr<string> p1(new string("dfss"));
unique_ptr<string> p2(p1); //错误,不支持拷贝
unique_ptr<string> p3;
p3 = p1; //错误,不支持赋值
但可以通过调用release或reset将指针的所有权从一个unique_ptr转移给另一个unique:
// 将所有权从p1转移给p2
unique_ptr<string> p2(p1.release()); //release置为空
unique_ptr<string> p3(new string("Trex"));
// 将所有权从p3转移给p2
p2.reset(p3.release()); //reset释放了p2原来指向的内存
虽然标准库中auto_ptr仍然存在,但使用它会有许多隐患,所以尽量不要使用。
八、weak_ptr
weak_ptr不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象。一旦最后一个指向对象的shared_ptr被销毁,即使有weak_ptr指向这个对象,对象也还是会被释放。这就是weak的体现。
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock。此函数检查weak_ptr是否仍存在,存在返回一个指向共享对象的shared_ptr。
if (shared_ptr<int> np = wp.lock()){ //如果np不为空则条件成立
// 在if中,np与p共享对象
}
###学习《C++ Primer》- 5的更多相关文章
- 学习C++ Primer 的个人理解(一)
<C++ Primer>这本书可以说是公认的学习C++最好的书,但我觉得不是特别适合作为教材,书中内容的顺序让人有些蛋疼.我个人认为初学此书是不能跳着看的.如果急于上手的话,我更推荐< ...
- 学习C++ Primer 的个人理解(九)
这一章介绍顺序容器,在之前的第三章中,了解到的vector就属于顺序容器的一种. 一个容器就是一些特定类型对象的集合. 除了vector,还有哪些顺序容器? vector: 大小可变,随机访问的速度很 ...
- 学习C++ Primer 的个人理解(三)
第三章,主要内容是字符串和数组.感觉作者的意图是希望读者可以早一点可以写出简单的小程序,并且可以早点接触迭代器这种思想. 在我看来,这种内容的难度并不大. 对于编程来说,最重要的应该是思想,类似vec ...
- 学习C++ Primer 的个人理解(二)
本身就一定基础的读者我想变量常量这些概念应该已经不是问题了.但是本章还是有几个重点,需要特别留意一下的: 1.初始化和赋值是不同的操作 2.任何非0值都是true 3.使用新标准列表初始化,在有丢失精 ...
- 学习C++.Primer.Plus 11 使用类
1.操作符重载 重载操作符的几个限制: a) 重载的至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符. b) 不能违反操作符原有来的句法规则. c) ...
- 学习C++.Primer.Plus 10 对象和类
1.类的声明和定义 类的声明和定义. 类声明的格式如下: class className { private://private 是类对象的默认访问控制,因此,可以省略 data member del ...
- 学习C++.Primer.Plus 8 函数探幽
1. 内联函数 普通函数调用: 存储调用指令的地址->将函数参数复制到堆栈->跳到函数地址执行代码(返回值放到寄存器)->跳回调用指令处 2. 当代码执行时间很短,且会被大量调用的 ...
- 学习C++.Primer.Plus 7 函数
C++的返回值类型不能是数组 函数原型中的变量名相当于点位符,因此不要求提供变量名. void cheers(int); C++中不指定参数列表时就使用活力号: void saybye(...); 通 ...
- 学习C++.Primer.Plus 6 分支语句和逻辑操作符
||. &&操作符是一个顺序点 < 操作符从左向右结合 ; < age < )//17<age为true, = 1,肯定 < 27.所以为整个条件为tru ...
- 学习C++.Primer.Plus 5 循环和关系表达式
C++将赋值表达式的值定义为左侧成员的值 赋值操作符是自右向左结合的 cout.setf(ios:: boolalpha);//调用设置标记,命令cout输出true或false,而非1或0. 任何表 ...
随机推荐
- 多个分布式系统如何共享使用一个固定公网IP
传统的做法,一个分布式业务系统就有一个中间件,一个中间件需要使用至少一个固定公网IP,这样的话,多个业务系统就需要使用多个固定公网IP. 大家知道,固定公网IP价格可是不菲的.能不能让多个分布式业务系 ...
- ISE和Modelsim联合仿真(转)
相信很多人会遇到过这个问题,不知如何让ISE调用Modelsim进行仿真.我也迷糊了不少时间,查查找找,终于弄明白了,所以有了本文,和大家分享一下.我尽量讲得详细点儿,多多上图. 我的环境:Windo ...
- WEB- 冻结TABLE的头和列
没认真去研究是怎么实现的,看到效果,心里觉的很牛,备注在这里 转载自:http://www.cnblogs.com/Microshaoft/archive/2011/08/10/2133434.htm ...
- jQuery插件- Autocomplete应用详解
项目中有时会用到自动补全查询,就像Google搜索框.淘宝商品搜索功能,输入汉字或字母,则以该汉字或字母开头的相关条目会显示出来供用户选择, autocomplete插件就是完成这样的功能. auto ...
- 测试JS基本类型以及对象的引用
自己敲的. 1 <script src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js&qu ...
- DNS服务未响应的简单解决办法
今天晚上下班回家,打开电脑,发现打不开网页了,同一个wifi环境下,我的手机是可以连接上的,网上搜了一大推,又是重启服务,又是重新填写dns服务地址,都不管用, 该怎么办呢??. 其实发现很简单,打开 ...
- 我的第一篇博客 ——【ToDoList】小程序开发
我是一只即将大四的大三狗,这是我的第一篇博客,说来惭愧.今年1月份,学校放寒假的时候开始自学的IOS,放假的时候比较起劲,看了一堆Object-C的视频,然后照着中英文对照的IOS基础开发教程,做了两 ...
- linux makefile: c++ 编程_基础入门_如何开始?
学习android 终究还是需要研究一下其底层框架,所以,学习c++很有必要. 这篇博客,算是linux(ubuntu) 下学习 c++ 的一个入门. 刚开始学习编程语言的时候,最好还是使用命令行操作 ...
- hdu 5120 Intersection 圆环面积交
Intersection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5 ...
- Android在MediaMuxer和MediaCodec用例 - audio+video
在Android多媒体类,MediaMuxer和MediaCodec这是一个相对年轻,他们是JB 4.1和JB 4.3据介绍. 前者被用来产生一个混合的音频和视频的多媒体文件.的缺点是,现在可以只支持 ...