【C++】笔记
文章平均质量分 77
关于一些书籍、视频等C++笔记.
江湖人称菠萝包
这个作者很懒,什么都没留下…
展开
-
【C++】05-C++内存管理机制-笔记(侯捷系列)
1、内存分配每一层面C++ Applications->C++ Library(std::allocator)->C++ primitives(new,new[],new(),::operator new(),...)->CRT(malloc/free)->O.S.API(such as HeapAlloc,VirtualAlloc,...)用法:void* p1 = malloc(512); // 512bytesfree(p1);void* p2 = ::o原创 2022-05-23 21:16:07 · 573 阅读 · 0 评论 -
【C++】04-C++新标准C++11&14-笔记(侯捷系列)
1、全文检索工具:Windows Grep。便于根据关键字查找标准库的源代码。2、确认自己编译器支持C++11。#define _cplusplus 201103Lstd::cout << _cplusplus;#if _cplusplus >= 201103L ...#else ...#endif3、使用数量不定的模板参数时,要注意递归的边界。void print(){}template<typename T, typename... Types原创 2022-05-23 21:15:34 · 396 阅读 · 0 评论 -
【C++】03-STL标准库与泛型编程-笔记(侯捷系列)
1、STL六大部件:容器、分配器、算法、迭代器、适配器、仿函数。2、begin()指向第一个元素,end()函数指向最后一个元素的下一个位置。迭代器概念上讲就是泛化的指针。Container<T> c;...写法①:Container<T>::iterator ite = c.begin();for(; ite!=c.end(); ++ite) ...写法②(since C++11):for(int i : { 2, 3, 5, 7, 9 }) .原创 2022-05-23 21:14:56 · 478 阅读 · 0 评论 -
【C++】02-C++面向对象高级编程(下)-笔记(侯捷系列)
1、当一个类需要转换成其他类型(任何一种前面已经定义过的类型,不一定是内置类型)时,需要使用转换函数。例如一个类如果要转换为double,则需定义函数:operator double() const { // ... return (double)(...);}2、加了explicit修饰符的构造函数是不允许隐式转换的。当构造函数只有一个实参(它可以有两个以上的形参,但是由于有默认实参,当构造该对象时,只要传入一个参数,就可以构造出该对象),就有可能在某种场景下出现隐式转换原创 2022-05-23 21:13:33 · 135 阅读 · 0 评论 -
【C++】01-C++面向对象高级编程(上)-笔记(侯捷系列)
1、在设计一个类的时候,数据应该尽量是private的,几乎没有例外。2、构造函数应该用冒号后面初值列的形式,不应该在构造函数的函数体里面去赋值。例如,A::A(int a) : m(a){ // 不应该用 m = a; 这种形式} 3、在设计一个函数的时候,如果这个函数不会改变数据,应该将这个函数修饰为const。例如,double real() const { return re; }假如不这么做,当一个用const修饰的对象去调用这个函数的时候,万一这个函数有可能会修改数据,原创 2022-05-23 21:11:52 · 125 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-汇总
一、C++ 并发世界同一进程内的所有进程都共用相同的地址空间,且所有线程都能直接访问大部分数据。每个线程都需要独立的栈空间,如果线程太多,就可能耗尽所属进程的可用内存或地址空间。管控线程的函数和类在中声明,而有关共享数据保护的声明则位于别的头文件中。每个线程都需要一个起始函数,新线程从这个函数开始执行。就应用程序的起始线程而言,该函数是main()。对于别的线程,其起始函数需要在std::thread对象的构造函数中指明。新线程启动后,起始线程继续执行。如果起始线程不等待新线程结束,就会一路执行原创 2022-05-04 18:13:52 · 2763 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-ChapterA-C++11 精要:部分语言特性
附录A、C++11 精要:部分语言特性右值引用int var = 42;int& ref = var; // 创建名为 ref 的引用,指向的模目标是变量 varint &i = 42; // 无法编译int const& i = 42; // 我们一般都能将右值绑定到 const 左值引用上int&& i = 42;int j = 42;int&& k = j; // 编译失败术语右值来自 C 语言,指只能原创 2022-05-04 18:12:24 · 702 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter9-高级线程管理
九、高级线程管理线程池最简单的实现形式是,采用数目固定的工作线程(往往与 std::thread::hardware_concurrency() 的返回值相等)。由于 std::packaged_task<> 的实例仅能移动而不可复制,但 std::funtion<> 要求本身所含的函数对象能进行拷贝构造,因此任务队列的元素不能用 std::function<> 充当。我们必须定制自己的类作为代替,以包装函数,并处理只移型别。这个类其实就是一个包装可调用对象的原创 2022-05-04 18:10:22 · 1015 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter5-C++ 内存模型和原子操作
五、C++ 内存模型和原子操作对象和内存区域C++ 标准只将“对象”定位为“某一存储范围”。位域有一项重要的性质:尽管相邻的位域分属不同对象,但照样算作同一内存区域。整个结构体就是一个对象,它由几个子对象构成,每个数据成员即为一个子对象。struct my_data{ int i; double d; unsigned bf1:10; int bf2:25; int bf3:0; int bf4:9; int i2; char原创 2022-05-04 18:09:13 · 720 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter4-并发操作的同步
四、并发操作的同步线程间的同步操作很常见,C++ 标准库专门为之提供了处理工具:条件变量和 future。另外,并发技术规约还提供了新式的同步工具:线程闩(latch)和线程卡(barrier)。让线程休眠100毫秒:std::this_thread::sleep_for(std::chrono::milliseconds(100));凭借条件变量等待条件成立C++ 标准库提供了条件变量的两种实现:std::condition_variable 和 std::condition_va原创 2022-05-04 18:07:01 · 1001 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter3-在线程间共享数据
三、在线程间共享数据用互斥保护共享数据在 C++ 中,我们通过构造 std::mutex 的实例来创建互斥,调用成员函数 lock() 对其加锁,调用 unlock() 解锁。C++ 标准库提供了类模板 std::lock_guard<>,针对互斥类融合实现了 RAII 手法:在构造时给互斥加锁,在析构时解锁,从而保证互斥总被正确解锁。std::mutex 和 std::lock_guard<> 都在头文件里声明。C++17 引入了一个新特性,名为类模板参数推断,对于原创 2022-05-04 18:06:12 · 939 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter2-线程管控
二、线程管控每个 C++ 程序都含有至少一个线程,即运行main()的线程,它由 C++ 运行时(C++ runtime)系统启动。发起线程任何可调用类型都适用于std::thread。包括函数指针、函数对象、lambda等,能让使用者对其进行函数调用操作。class Func{public: void operator() () const { do_something(); }};Func f;std::thread myThread(f原创 2022-05-04 18:04:57 · 521 阅读 · 0 评论 -
【C++】《C++ 并发编程实战 (第2版) 》笔记-Chapter1-C++ 并发世界
一、C++ 并发世界同一进程内的所有进程都共用相同的地址空间,且所有线程都能直接访问大部分数据。每个线程都需要独立的栈空间,如果线程太多,就可能耗尽所属进程的可用内存或地址空间。管控线程的函数和类在中声明,而有关共享数据保护的声明则位于别的头文件中。每个线程都需要一个起始函数,新线程从这个函数开始执行。就应用程序的起始线程而言,该函数是main()。对于别的线程,其起始函数需要在std::thread对象的构造函数中指明。新线程启动后,起始线程继续执行。如果起始线程不等待新线程结束,就会一路执行原创 2022-05-04 18:03:26 · 228 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter16-模板与泛型编程
笔记:一、定义模板1、面向对象编程(OOP)和泛型编程都能处理在编写程序时不知道类型的情况。不同之处在于:OOP能处理类型在程序运行之前都未知的情况;而在泛型编程中,在编译时就能获知类型了。2、模板是C++泛型编程的基础。一个模板就是一个创建类或函数的蓝图或者说公式。3、在模板定义中,模板参数列表不能为空。在模板参数列表中,typename和class没有什么不同。4、当我们调用一个函数模板时,编译器(通常)用函数实参来为我们推断模板实参。5、编译器用推断出的模板参数来为我们实例化一个特定版本的原创 2021-07-12 09:04:30 · 122 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter15-面向对象程序设计
笔记:一、OOP:概述1、面向对象程序设计基于三个基本概念(也是其核心思想):数据抽象、继承和动态绑定。通过使用数据抽象,我们可以将类的接口与实现分离;使用继承,可以定义相似的类型并对其相似关系建模;使用动态绑定,可以在一定程度上忽略相似类型的区别,而以统一的方式使用它们的对象。2、对于某些函数,基类希望它的派生类各自定义适合自身的版本,此时基类就将这些函数声明成虚函数。3、派生类必须在其内部对所有重新定义的虚函数进行声明。派生类可以在这样的函数之前加上virtual,但是并不是非得这么做。3、原创 2021-07-12 09:04:21 · 130 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter14-重载运算与类型转换
笔记:一、基本概念1、当一个重载的运算符是成员函数时,this绑定到左侧运算对象。成员运算符函数(显式)参数数量比运算对象的数量少一个。2、通常情况下,不应该重载逗号、取地址、逻辑与、逻辑或运算符。3、下面的准则有助于我们在将运算符定义为成员函数还是普通的非成员函数做出抉择:①赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员。②复合赋值运算符一般来说应该是成员,但并非必须,这一点与赋值运算符略有不同。③改变对象状态的运算符或者与给定类型密切相关的运算符,如递增原创 2021-07-12 09:04:12 · 99 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter13-拷贝控制
笔记:一、拷贝、赋值与销毁1、拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么。拷贝和移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么。析构函数定义了当此类型对象销毁时做什么。我们称这些操作为拷贝控制操作。2、如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。拷贝构造函数的第一个参数必须是一个引用类型(因为拷贝构造函数被用来初始化非引用类类型参数,否则定义就是死循环)。虽然我们可以定义一个接收非const引用的拷贝构造原创 2021-07-12 09:04:01 · 112 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter12-动态内存
笔记:一、动态内存与智能指针1、静态内存是用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数内的非static对象。分配在静态或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在其定义的程序块运行时才存在;static对象在使用之前分配,在程序结束时销毁。2、除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间或堆。程序用堆来存储动态分配的对象——即,那么在程序运行时分配的对象。动态对象的生存期由程序来控制。3、新标准提原创 2021-07-12 09:03:52 · 100 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter11-关联容器
笔记:一、使用关联容器1、关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的。与之相对,顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。2、关联容器支持高效的关键字查找和访问。两个主要的关联容器类型是map和set。map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。set中每个元素只包含一个关键字;set支持高效的关键字查询操作——检查一个给定关键字是否在set中。3、当从map中提取一个元素时,会得到一个pa原创 2021-07-12 09:03:41 · 89 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter10-泛型算法
笔记:一、概述1、大多数算法都定义在头文件algorithm中。标准库还在头文件numeric中定义了一组数值泛型算法。2、泛型算法本身不会执行容器的操作,它们只会运行于迭代器之上,执行迭代器的操作。泛型算法运行于迭代器之上而不会执行容器操作的特性带来了一个令人惊讶但非常必要的编程假定:算法永远不会改变底层容器的大小。算法可能改变容器中保存的元素的值,也可能在容器内移动元素,但永远不会直接添加或删除元素。当一个算法操作插入器时,迭代器可以完成向容器添加元素的效果,但算法自身永远不会做这样的操作。原创 2021-07-11 19:12:52 · 116 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter9-顺序容器
笔记:一、顺序容器概述1、元素在顺序容器中的顺序与其加入容器时的位置相对应。关联容器中元素的位置由元素相关联的关键字值决定。2、顺序容器类型:①vector:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。②deque:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。③list:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。④forward_list:单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。(原创 2021-07-11 19:12:16 · 112 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter8-IO库
笔记:一、IO类1、iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。2、我们不能拷贝或对IO对象赋值。由于不能拷贝IO对象,因此我们也不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const。3、《C++ Primer 5e》P279-表8.2列出了IO类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态。(例如原创 2021-07-11 19:11:11 · 86 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter7-类
笔记:一、定义抽象数据类型1、类的基本思想是数据抽象和封装。数据抽象是一种依赖于接口和实现分离的编程(以及设计)技术。类的接口包括用户所能执行的操作;类的实现则包括类的数据成员、负责接口实现的函数体以及定义类所需的各种私有函数。封装实现了类的接口和实现的分离。封装后的类隐藏了它的实现细节,也就是说,类的用户只能使用接口而无法访问实现部分。2、成员函数的声明必须在类的内部,它的定义则既可以在类的内部也可以在类的外部。3、任何对类成员的直接访问都被看作this的隐式引用。this是一个常量指针,我们原创 2021-07-11 19:10:33 · 112 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter6-函数
笔记:一、函数基础1、在C++语言中允许重载函数,也就是几个不同的函数可以使用同一个名字。2、实参是形参的初始值。尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序。编译器能以任意可行的顺序对实参求值。实参的类型必须与对应的形参类型匹配,但有时存在实参隐式转换,例如实参是double、形参是int。3、任意两个形参不能同名,而且函数最外层作用域中的局部变量也不能使用与函数形参一样的名字。4、函数的返回类型不能是数组类型或函数类型,但可以是指向数组或函数的指针。5、在C++语言中,名字有原创 2021-07-11 19:09:58 · 157 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter5-语句
笔记:一、简单语句1、最简单的语句是空语句,空语句只含有一个单独的分号。一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会用到空语句。使用空语句时应该加上注释,从而令读这段代码的人知道该语句是有意省略的。空块的作用等价于空语句。二、语句作用域三、条件语句1、switch语句首先对括号里的表达式求值,该表达式紧跟在关键字switch的后面,可以是一个初始化的变量声明。表达式的值转换成整数类型,然后与每个case标签的值比较。break语句的作用是中断当前的控制流。ca原创 2021-07-11 19:07:00 · 127 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter4-表达式
笔记:一、基础1、C++定义了一元运算符和二元运算符。作用于一个运算对象的运算符是一元运算符,以此类推。2、在表达式求值的过程中,运算对象常常由一种类型转换成另外一种类型。例如,尽管一般的二元运算符都要求两个运算对象的类型相同,但是很多时候即使运算对象的类型不相同也没有关系,只要它们能被转换成同一种类型即可。小整数类型(如bool、char、short等)通常会被提升成较大的整数类型,主要是int。3、当运算符作用于类类型的运算对象时,用户可以自行定义其含义。因为这种自定义的过程事实上是为已存在原创 2021-07-11 19:06:35 · 170 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter3-字符串、向量和数组
笔记:一、命名空间的using声明1、string表示可变长的字符序列,vector存放的是某种给定类型对象的可变长序列。2、using声明具有如下的形式:using namespace::name;3、位于头文件的代码一般来说不应该试用using声明。这是因为头文件的内容会拷贝到所有引用它的文件中去。对于某些程序来说,由于不经意间包含了一些名字,反而可能产生始料未及的名字冲突。二、标准库类型string1、下面是初始化string对象最常用的一些方式:string s1; ...原创 2021-07-11 19:05:56 · 178 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter2-变量和基本类型
笔记:一、基本内置类型1、选择类型的一些准则:①当明确知晓数值不可能为负时,选用无符号类型;②使用int执行整数运算。在实际应用中,short常常显得太小而long一般和int有一样的尺寸。如果你的数值超过了int的表示范围,选用long long。③在算术表达式中不要使用char或bool,只有在存放字符或布尔值时才使用它们。因为类型char在一些机器上是有符号的,而在另一些机器上又是无符号的,所以如果使用char进行运算特别容易出问题。如果你需要使用一个不大的整数,那么明确指定它的类型是sig原创 2021-07-11 19:05:12 · 140 阅读 · 0 评论 -
【C++】《C++ Primer 5th》笔记-Chapter1-开始
笔记:1、在大多数系统中,main的返回值被用来指示状态。返回值0表明成功,非0的返回值的含义由系统定义,通常用来指出错误类型。2、不同编译器使用不同的后缀命名约定,最常见的包括.cc、.cxx、.cpp、.cp及.C。3、编译器生成一个可执行文件。Windows系统会将这个可执行文件命名为xxx.exe。Unix系统中的编译器通常将可执行文件命名为a.out。4、标准库还定义了其他两个ostream类型对象,名为cerr和clog(发音分别为see-err和see-log)。我们通常用cerr来输原创 2021-07-11 19:03:36 · 100 阅读 · 0 评论