==========================================================================
day08
==========================================================================
1. map又称为关联数组。

使用map来写单词计数程序

E1: map<string, size_t> word_count;
string word;
while (cin >> word) {
++word_count[word]; // map中的下标操作符[],如果word不在map中,则下标操作符会添加一个新元素.所以[]只可以用在非const的map
// 有时候我们只想知道一个元素是否在map中,但在不存在时并不想添加元素,就不能使用下标操作符
}
for (const auto &w : word_count)
cout << w.first << " occurs " << w.second << ((w.second > 1) ? "times" : "time")<<endl;

E2: map<string, size_t> word_count;
string word;
while (cin >> word) {
auto ret = word_count.insert({word,1}); // 插入一个元素,关键字为word,值为1.如果map中已存在,则什么都不做
if (!ret.second) // word 已在map中
++ret.first->second; // 递增计数器
}
for (const auto &w : word_count)
cout << w.first << " occurs " << w.second << ((w.second > 1) ? "times" : "time") << endl;

2.动态内存管理

#include<memory>

为了更容易更安全的使用动态内存,标准库提供了两种智能指针类型来管理动态对象。
shared_ptr 允许多个指针指向同一个对象 用法: shared_ptr<string> // 表示指针可以指向的类型为string
unique_ptr 独占所指的对象

标准库还定义了weak_ptr,是一种弱引用,指向shared_ptr所管理的对象

3.内存耗尽。 尽管一般内存足够,但还是可能出现内存耗尽的情况。当内存耗尽,new就会失败,默认情况下,就会抛出一个bad_alloc的异常。
我们可以在出现这种情况时阻止抛出异常,并返回一个空指针: int *p = new (nothrow) int; //如果分配失败,返回一个空指针
这种形式的new称为定位new(placement new) bad_alloc和nothrow都定义在#include<new>中

4.我们传递给delete的指针必须是指向动态分配的内存,或者是一个空指针(nullptr)
eg: int i,*pi1 = &i,*pi2 = nullptr;
double *pd = new double(33),*pd2 = pd;
delete i; //错误,i不是一个指针
delete pi1; //未定义的行为,pi1指向的是一个局部变量 编译器并不会报错
delete pi2; //正确,释放一个空指针总是没错的
delete pd; //正确
delete pd2; //未定义的行为,pd2指向的内存以及被释放过了 编译器并不会报错

delete之后重置指针值:
当我们delete一个指针后,指针值就变得无效了。虽然指针无效了,但在许多机器上指针仍然保存着(已经释放了的)动态内存的地址。在delete之后
指针就变成了悬空指针,即指向一块曾经保存数据但现在已经无效的内存的指针。
避免悬空指针的方法是,delete后,将指针置为nullptr。
但这也仅仅是有限的保护:当多个指针指向相同的内存,delete内存后重置指针为空的方法只对这个指针有效,对其他仍指向(已释放的)内存的指针是没有
作用的。
eg: int *p = new int(42);
autp q = p; // q和p指向相同的内存
delete p; // p和q均变为无效
p = nullptr; // 指出p不再绑定任何对象 但重置p对q没有任何作用,q还是个悬空指针。

5. 注意,内置类型的动态内存分配,需要显式地初始化 : int *p = new int(5); // 初始化为5
否则,其指向的值是未定义的。 而一些内置类或自定义有默认构造函数的类型,如果不显式初始化就会进行默认初始化。

6. make_shared函数类似于容器的emplace()函数(考虑insert与emplace的区别),make_shared用其参数来构造给定类型的对象。
例如,make_shared<string>时传递的参数必须与string的某个构造函数相匹配。
make_shered<string>(10,'a'); 如果什么参数都不传递,则对象进行值初始化。

7.智能指针与new的混用
如果我们不初始化一个智能指针,他就会被初始化为一个空指针。 shared_ptr<int> sp; // 空指针
除了使用make_shared函数初始化智能指针,我们还可以用new返回的指针来初始化智能指针。
shared_ptr<int> p(new int(42)); // 正确,可以使用直接初始化的形式
shared_ptr<int> p1 = new int(1024); // 错误,智能指针的构造函数是explicit的,不能将内置指针隐式转换为智能指针,必须使用直接初始化的形式

【不要将智能指针与普通指针混用】
考虑如下:
void process(shared_ptr<int> ptr)
{
//使用ptr
} // ptr离开作用域,被销毁

上述函数的参数是以传值方式传递的,因此实参会被拷贝到ptr中。拷贝一个shared_ptr会递增其引用计数。因此process运行过程中,引用计数至少为2

shared_ptr<int> p(new int(42)); // 引用计数为1
process(p); // 拷贝p递增它的引用计数; 变为2
int i = *p; // 出了process函数,局部变量ptr被销毁,引用计数变为1,所以仍然可以使用p指向的这块内存

再考虑如下:
int *x(new int(1024));
process(shared_ptr<int>(x)); // 引用计数为1
int j = *x; // 未定义的行为,x变为了空悬指针。
上述调用,我们把一个临时的shared_ptr传给了process,当调用结束,这个临时对象就被销毁了,引用计数就会递减,变为0,因此,临时对象被销毁,
它所指的内存被释放,但x继续指向已经被释放的内存,从而成了一个空悬指针。

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

8.之前一直以为野指针和空悬指针一个意思,但错了。
空悬指针(dangling pointer):指向已经销毁的对象或已经回收的地址。
野指针:没有初始化的指针就是野指针。 如:int *p;

9.永远不要用get函数初始化另一个智能指针或为智能指针赋值。
get函数,p.get() ,返回p中保存的指针,返回的是一个内置指针。
get函数是为这样一种情况设计的:我们需要向不能使用智能指针的代码传递一个内置指针。

要非常注意的一点是:get返回的指针,不能用delete

shared_ptr<int> p(new int(42));p指向
int *q = p.get();
....
delete q; // 未定义的行为,因为智能指针p会自动释放内存,而再调用delete q 就会造成了二次释放内存。

10. 因为shared_ptr可能有多个指向了同一块内存,在改变指向的底层对象之前,我们先检查自己是不是当前对象仅有的用户,
如果不是,在改变之前要制作一份新的拷贝。 用到reset函数,其中一种的参数是一个内置指针。(reset函数有三种)
用法:p.reset(q); 令p指向q

if(!p.unique())
p.reset(new string(*p)); // 我们不是唯一用户,分配新的拷贝。
*p += newVal; //现在我们是唯一用户了,可以改变对象的值。

C++Primer笔记-----day08的更多相关文章

  1. C++ Primer笔记

    C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...

  2. C++ Primer 笔记(1)基础中的战斗机 输入输出 对输入不定数据处理

    今天打算再重新好好的看一遍C++ Primer这本很经典的书籍,笔记开始: 1.每个C++程序都包含一个或者多个函数,其中必须有一个main,操作系统通过调用main入手运行程序: 2.函数包括:返回 ...

  3. C++ Primer 笔记 第一章

    C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...

  4. C++primer笔记之顺序容器

    最近又重新拾起C++primer,发现每一次看都会有不同的体验,但每一次看后因为不常用,忘记得很快,所以记笔记是很关键的一环,咋一看是浪费时间,实际上是节省了很多时间.下面就把这一节的内容做一个简单的 ...

  5. c++ primer 笔记 (一)

    昨天开始看的<C++ Primer>,确实不错.希望这周抓紧看完,每天做下笔记,以便以后复习. main函数返回一个值给操作系统   操作系统通过main函数返回的值来确定程序是否成功执行 ...

  6. C++ Primer笔记(1)——连续读取数据、类型对应的尺寸、类型转换、字符串分行写法

    这次要看看C++ Primer,这本基本上就是必读书籍了.下面的内容就是一些之前没有学过的知识的笔记. 读取数量不定的输入数据 虽然很简单,但是还是记一下: #include <iostream ...

  7. C++Primer笔记(3)

    标准库类型string表示可变长的字符序列,使用前先包含string头文件.(哈哈,终于可以逃脱C语言中的str函数系列了.)因为是标准库的一部分,所以string被定义在命名空间std中.所以你懂该 ...

  8. C++ Primer 笔记 第三章

    C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...

  9. C++ Primer 笔记 第二章

    C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...

随机推荐

  1. Understanding Safari Reader

    Interesting enough to find out the Reader function in Safari is actually Javascript and there are ma ...

  2. Linux安装python2.7、pip和setuptools

    一.说明 CentOS6.5自带python环境为2.6,公司的python环境为2.7. 为了避免出现以后代码出现版本差异,所以把自带的2 .6版本升级到了2.7,过程十分曲折.... 中途遇到的问 ...

  3. PHP 7.0 EOL (PHP 技术支持相关)

    PHP 7.0 EOL (PHP 支持相关) PHP 5.6 于 2018-12-31 结束(EOL) 从图表看出,PHP 7.0 是一个过渡版本,现在已经 EOL. 而 PHP 7.1 将于明年年底 ...

  4. Microsoft.Crm.Setup.SrsDataConector.RegisterServerAction 操作失败 Requested value 'Geo' was not found 的解决方法

    error installing ssrs data connector on sql server for dynamics crm 2011 I think the post title says ...

  5. 如何随机从数据库表中抽一条数据的SQL语句

    NewID() 方法返回一个 GUID,如:EE95A489-B721-4E8A-8171-3CA8CB6AD9E4 在 select 表的时候,再增加一列为 NewID() 就可以了. SQL 语句 ...

  6. autoit 中文API

    中文API 参考地址: http://www.jb51.net/shouce/autoit/ 虫师的selelnium里面也有简单的说 环境搭建+上传弹窗的小案例

  7. Find minimum continuous subsequence tags

    Given targetList, a list of strings representing the desired tags, and availableTagList, a list of s ...

  8. 新生代老年代GC组合

    新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中 在执行机制上JVM提供了串行GC(SerialGC).并行 ...

  9. 1016 Phone Bills (25 分)

    1016 Phone Bills (25 分) A long-distance telephone company charges its customers by the following rul ...

  10. AJAX XML 实例

    AJAX XML 实例 下面的例子将演示网页如何使用 AJAX 来读取来自 XML 文件的信息 <!DOCTYPE html> <html> <head> < ...