C++ Primer(第5版) 全书重点学习笔记

这篇具有很好参考价值的文章主要介绍了C++ Primer(第5版) 全书重点学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

第12章 动态内存

12.1 动态内存与智能指针

12.1.6 weak_ptr

12.2 动态数组

12.2.1 new和数组

12.2.2  allocator类


C++ Primer(第5版) 全书重点学习笔记,C++,c++,C++ Primer

 

第12章 动态内存

12.1 动态内存与智能指针

12.1.6 weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。

当我们创建一个weak ptr时,要用一个shared ptr来初始化它:

auto p = make_shared<int>(42);
weak_ptr<int> wp(p);

由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock检查weak_ptr指向的对象是否仍存在。如果存在,lock返回一个指向共享对象的shared ptr。

if (shared_ptr<int> np = wp.lock()) { 
    // 只有当1ock调用返回true时我们才会进入if语句体
}

12.2 动态数组

12.2.1 new和数组

为了让new分配一个对象数组,我们要在类型名之后跟一对方括号,在其中指明要分配的对象的数目。方括号中的大小必须是整型,但不必是常量。

//调用get size确定分配多少个int
int *pia = new int[get size()]; //pia指向第一个int

也可以用一个表示数组类型的类型别名来分配一个数组,这样,new表达式中就不需要方括号了:

typedef int arrT[42];    //arrT表示42个int的数组类型
int *p = new arrT;    //分配一个42个int的数组;p指向第一个int
int *p = new int[42];   //编译器执行这个表达式时还是会用new[]

 typedef用法:【C/C++】中【typedef】用法大全_c++中typedef的用法

当用new分配一个数组时,我们并未得到一个数组类型的对象,而是得到一个数组元素类型的指针。即使我们使用类型别名定义了一个数组类型,new也不会分配一个数组类型的对象。在上例中,new返回的是一个元素类型的指针。
由于分配的内存并不是一个数组类型,因此不能对动态数组调用begin或end。这些函数使用数组维度来返回指向首元素和尾后元素的指针。出于相同的原因,也不能用范围for语句来处理动态数组中的元素。

初始化动态分配对象的数组:默认情况下,new分配的对象,不管是单个分配的还是数组中的,都是默认初始化的。可以对数组中的元素进行值初始化方法是在大小之后跟一对空括号。在新标准中,我们还可以提供一个元素初始化器的花括号列表。

int* pia = new int[10];    //10个未初始化的int
int* pia2 = new int[10]();   //10个值初始化为0的int       
    
int* pia3 = new int[10]{ 0,1,2,3,4,5,6,7,8,9 };   //10个1nt分别用列表中对应的初始化器初始化
string* pia4 = new string[10]{ "a","an","the",string(3,'x') };   //10个string,前4个用给定的初始化器初始化,剩余的进行值初始化

动态分配一个空数组是合法的:当我们用new分配一个大小为0的数组时,new返回一个合法的非空指针,但此指针不能解引用一毕竟它不指向任何元素。

char arr[0];     // 错误:不能定义长度为0的数组
char* cp = new char[0];      //正确:但cp不能解引用

C++ Primer(第5版) 全书重点学习笔记,C++,c++,C++ Primer

释放动态数组:为了释放动态数组,我们使用一种特殊形式的delete一在指针前加上一个空方括号对。当我们释放一个指向数组的指针时,空方括号对是必需的:它指示编译器此指针指向一个对象数组的第一个元素。如果我们在delete一个指向数组的指针时忽略了方括号其行为是未定义的。

delete cp;    // p必须指向一个动态分配的对象或为空
delete [] cp;    //pa必须指向一个动态分配的数组或为空

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

当一个unique ptr指向一个数组时,我们不能使用点和箭头成员运算符。毕竟unique ptr指向的是一个数组而不是单个对象,因此这些运算符是无意义的。当一个unique ptr指向一个数组时,我们可以使用下标运算符来访问数组中的元素。

// up指向一个包含10个未初始化int的数组	
unique_ptr<int[]> up(new int[10]);
for (size_t i = 0; i != 10; ++i) {
	up[i] = i;
	cout << "up" << "[" << i << "]:" << up[i] << endl;
}
//自动用delete[]销毁其指针
up.release();

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

shared_ptr未定义下标运算符,而且智能指针类型不支持指针算术运算。因此,为了访问数组中的元素,必须用get获取一个内置指针,然后用它来访问数组元素。

 

12.2.2  allocator类

allocator类:标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来。它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。

为了定义一个allocator对象,我们必须指明这个allocator可以分配的对象类型。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对齐位置。

allocator<string> alloc;    //可以分配string的allocator对象
auto const p = alloc.allocate(8);    //分配n个未初始化的string

allocator分配未构造的内存:allocator分配的内存是未构造的(unconstructed)。我们按需要在此内存中构造对象。在新标准库中,construct成员函数接受一个指针和零个或多个额外参数,在给定
位置构造一个元素。

auto q = p;    // q指向最后构造的元素之后的位置
alloc.construct(q++);    //*q为空字符串
alloc.construct(q++, 10, 'c');    //*q为cccccccccc
alloc.construct(q++, "hi");    //*g为hi!

为了使用allocate返回的内存,我们必须用construct构造对象。使用未构造的内存,其行为是未定义的。

当我们用完对象后,必须对每个构造的元素调用destroy来销毁它们。函数destroy接受一个指针,对指向的对象执行析构函数:

while(q!=p)
    alloc.destroy(--q);  //释放我们真正构造的string

在循环开始处,q指向最后构造的元素之后的位置。我们在调用destroy之前对q进行了递减操作。因此,第一次调用destroy时,q指向最后一个构造的元素。最后一步循环中我们destroy了第一个构造的元素,随后g将与p相等,循环结束。 

释放内存通过调用deallocate来完成

alloc.deallocate(p, n);

拷贝和填充未初始化内存的算法 :标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象,它们都定义在头文件memory中。文章来源地址https://www.toymoban.com/news/detail-643571.html

uninitialized_copy(b,e,b2) 从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存中。b2指向的内存必须足够大,能容纳输入序列中元素的拷贝
uninitialized_copy_n(b,n,b2) 从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中
uninitialized_fill(b,e,t) 在迭代器b和e指定的原始内存范围中创建对象,对象的值均为t的拷贝
uninitialized_fill_n(b,n,t) 从迭代器b指向的内存地址开始创建n个对象。b必须指向足够大的未构造的原始内存,能够容纳给定数量的对象

到了这里,关于C++ Primer(第5版) 全书重点学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 《c++ primer笔记》第十三章 拷贝控制

    1.1拷贝构造函数 ​ 如果一个构造函数的第一个参数是自身类类型的 引用 ,且任何额外参数都由默认值,则此构造函数成为拷贝构造函数。 拷贝构造函数在某些情况下会被隐式地使用,所以不能定义为 expicit 。 合成拷贝构造函数 ​ 合成某某函数 一般出现在我们没定义该函

    2023年04月25日
    浏览(15)
  • C++标准库 -- 顺序容器 (Primer C++ 第五版 · 阅读笔记)

    C++标准库 -- 顺序容器 (Primer C++ 第五版 · 阅读笔记)

    所有容器类都共享公共的接口,不同容器按不同方式对其进行扩展。 这个公共接口使容器的学习更加容易—我们基于某种容器所学习的内容也都适用于其他容器。 每种容器都提供了不同的性能和功能的权衡。 下表列出了标准库中的顺序容器, 所有顺序容器都提供了 快速顺序

    2023年04月17日
    浏览(12)
  • C++标准库 -- 泛型算法 (Primer C++ 第五版 · 阅读笔记)

    C++标准库 -- 泛型算法 (Primer C++ 第五版 · 阅读笔记)

    顺序容器只定义了很少的操作:在多数情况下,我们可以添加和删除元素访问首尾元素、确定容器是否为空以及获得指向首元素或尾元素之后位置的迭代器。 我们可以想象用户可能还希望做其他很多有用的操作:查找特定元素、替换或删除一个特定值、重排元素顺序等。 标准库

    2023年04月21日
    浏览(17)
  • 《C++ Primer》--学习4

    《C++ Primer》--学习4

    局部静态对象 在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁,在此期间即使对象所在函数结束执行也不会对它有影响  重载对作用域的一般性质没有什么改变,如果在内层作用域中声明名字,它将隐藏外层作用域中声明的同名实体。在不同

    2024年02月09日
    浏览(7)
  • 《C++ Primer》--学习12

    《C++ Primer》--学习12

    除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称为 自由空间  或  堆 ,程序用堆来存储 动态分配 的对象 智能指针负责自动释放所指向的对象 shared_ptr 类   智能指针也是模板      

    2024年02月13日
    浏览(7)
  • C++ Primer 5th 阅读笔记:变量和基本类型

    C++ Primer 5th 阅读笔记:变量和基本类型

    内建类型 ,如整型,字符型等; 变量 ,为值绑定的一个名字; 表达式和语句 ,操作值。 分支和循环 ,允许我们条件执行和重复执行; 函数 ,定义抽象计算单元。 自定义类型; 标准库。 学习语言的基本知识和标准库。 内建类型; 简要介绍自定义类。 定义了数据的意义

    2024年02月02日
    浏览(11)
  • 【c++ primer 笔记】第 16章 模板与泛型编程

    【c++ primer 笔记】第 16章 模板与泛型编程

    🎉作者简介:👓 博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢 c + + , g o , p y t h o n , 目前熟悉 c + + , g o 语言,数据库,网络编程,了解分布式等相关内容 textcolor{orange}{博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c+

    2024年02月20日
    浏览(12)
  • C++ Primer Plus笔记: 2023.06.05 AND 2023.06.06

    1.在C++的赋值语句: 赋值将从右向左进行,首先,88被赋值给steinway,然后,steinway的值(现在是88)被赋给baldwin,然后baldwin的值88被赋给yamaha。 2.类与对象: ** 类是用户定义的一种数据类型。要定义类,需要描述它能够表示什么信息和可对数据执行哪些操作,类之于对象就像

    2024年02月08日
    浏览(11)
  • C++ Primer Plus 第6版 读书笔记(8)第 8章 函数探幽

    本章内容包括: 通过第 7 章,您了解到很多有关 C++函数的知识,但需要学习的知识还很多。C++还提供许多新的函 数特性,使之有别于 C 语言。新特性包括内联函数、按引用传递变量、默认的参数值、函数重载(多态) 以及模板函数。 本章介绍的 C++在 C 语言基础上新增的特

    2024年02月15日
    浏览(13)
  • C++ Primer阅读笔记--对象移动(右值引用、移动迭代器和引用限定符的使用)

    目录 1--右值引用 2--std::move 3--移动构造函数 4--移动赋值运算符 5--移动迭代器 6--引用限定符         右值引用必须绑定到右值的引用,通过 获得右值引用;         右值引用只能绑定到 临时对象 (即将被销毁的对象),即所引用的对象将要被销毁,对象没有其他用户;

    2024年02月10日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包