![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C++深入学习笔记
文章平均质量分 58
慎铭
合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。
展开
-
C++深入学习笔记(21)—— 算法为什么不改变容器的大小?
泛型算法的的一大优点是“泛型”,也就是一个算法可以用于多个不同类型的数据类型,这也是STL的核心——算法与所操作的数据结构分离。 我们知道,迭代器的功能之一便是为算法进行服务,那么它是如何服务于算法的呢?要做到数据结构与算法分离,重要的技术手段就是使用迭代器作为两者之间的桥梁。可以说,算法根本就不知道有容器这个东西存在,它从来不对容器进行任何操作,只是对通过迭代器传输进来的一段序列进行处理,因此它从来不与特定的容器所绑定,从而实现了泛型。每个容器都有自己特定的迭代器,但是对于算法来说,既然是泛型算法原创 2021-11-08 16:57:50 · 751 阅读 · 0 评论 -
C++深入学习笔记(20)—— 泛型算法结构
算法形参模式 大多数的算法都有如下四种形式:alg(beg, end, args);alg(beg, end, dest, args);alg(beg, end, beg2, args);alg(beg, end, beg2, end2, args); 其中alg是算法的名字,beg和end表示算法所操作的范围。几乎所有的算法都要接受一个数出范围,是否有其它的参数依赖于要具体执行的操作。这里的beg, beg2, end, end2, dest都是迭代器参数。因此我们说迭代器有很大一部分都原创 2021-11-07 22:31:18 · 471 阅读 · 1 评论 -
C++深入学习笔记(19)—— 迭代器
iterator头文件中,除了为每个容器所定义的迭代器外,标准库中还额外定义了其它的迭代器类型,如下。插入迭代器(inset iterator):该类迭代器被绑定到一个容器上,可用来向容器中插入元素。流迭代器(stream iterator):该类迭代器被绑定到输入或者输出流上,可以用来遍历有关联的IO流。反向迭代器(reverse iterator):这些迭代器向后移动而不是向前移动。除了forward_list之外的标准库容器都有反向迭代器。(从头至尾的方向为前,从尾至头的方向为后。)插入原创 2021-11-07 15:42:22 · 477 阅读 · 0 评论 -
C++深入学习笔记(18)—— 定制操作(lambda表达式)
很多算法都会比较输入序列中的元素。默认情况下,这类算法使用元素类型的>或==运算符来比较。标准库还为这些算法定义了额外的版本,允许我们提供自己定义的操作来代替默认运算符。例如,我们知道sort算法默认的是按照<运算符来进行排序的,但是可能我们希望的排序顺序与<所定义的顺序不同,或者干脆我们就想让它是按照>运算符来进行排序的,在这些情况下,都需要重载sort的默认行为。我们就以sort算法为例,假如我们需要让它进行降序排序,那么它将接受第三个参数,该参数称为谓词谓词谓词是一个可原创 2021-10-21 22:23:41 · 233 阅读 · 1 评论 -
C++深入学习笔记(17)—— string类的数值转换
废话不多说,直接上代码int a = 123;string s = to_string(a); // 将整数a转换为字符表示形式,s = "123"double d = stod(s); // 将字符串转换为浮点数注意: 要转换为数值的string中第一个非空白符必须是树脂中可能出现的字符。string s = "PI = 3.14";pi 的值为3.14double pi = stod(s.substr(s.find_first_of("+-.0123456789")));在st原创 2021-10-17 21:39:29 · 190 阅读 · 0 评论 -
C++深入学习笔记(16)—— vector对象是如何增长的
我们知道,为了实现高效的随机访问,容器中的元素应该是物理上和逻辑上连续存储的。因此如果我们想容器中添加新的元素,会发生什么呢?容器会分配新的空间来保存已有的元素和新的元素,再将已有的元素从旧容器中拷贝过来,在添加新的元素,释放旧的空间。如果我们没添加一个新的元素就进行一次这样的操作,那么性能将会慢到我们不可接受。那么标准库容器采用了什么样的策略来减少内存重新分配的次数呢?当容器不得不进行如上操作是,容器通常会开辟一个比新空间更大的内存空间。容器预留这些空间作为备用,因此我们如果再次插入新的元素的话,就不需原创 2021-10-17 21:04:48 · 90 阅读 · 0 评论 -
C++深入学习笔记(15)—— 构造函数深探
使用构造函数初始值有时候我们可以忽略成员初始化和赋值之间的差异,但是并非总是这样的,如果成员是const类型或者引用类型的话,必须将其初始化,如果成员为类类型切该类没有默认构造函数的话,那么也应当将其初始化,否则编译器会报错class CTest{public: CTest(int i);private: int a; const int b; int &ra;}CTest::CTest(int i): a(i) {} // 错误,因为b和ra没有被初始化CTest::C原创 2021-10-12 10:57:33 · 106 阅读 · 0 评论 -
C++深入学习笔记(14)—— 可变数据成员
如果我们希望能够修改类的某个数据成员,即便是在一个const 成员函数内,可以通过在变量的声明中加入mutable关键字来做到。一个可变数据成员永远都不会是const,即便它是const对象的成员,因此const成员函数可以改变一个可变成员的值。class A{public: voud f() const;private: mutable int i;};void A::f() const{ ++i; // 在const成员函数内,i的值仍然可以改变。}即i时一个可变数据成员原创 2021-10-11 12:18:25 · 234 阅读 · 0 评论 -
C++深入学习笔记(13)—— 友元的声明
在类的定义中进行友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数声明。如果我们要调用友元函数,那么我们就必须在友元声明之外再对函数进行一次声明。为了使友元函数对类的用户可见,我们通常将友元的函数声明与类放在同一个头文件中。虽然有些编译器并未强制限定友元函数必须在使用之前在类的外部进行声明,但是我们最好这样做,因为如果更换了一个有如此强制要求的编译器我们也无须对代码进行改动。...原创 2021-10-11 10:22:00 · 635 阅读 · 0 评论 -
C++深入学习笔记(12)——构造函数
1.构造函数不能被声明为const,当我们创建类的一个const对象时,知道构造函数完成初始化过程的时候,对象才真正的取得其“常量属性”。2.如果我们没有显式的定义任何构造函数的话,那么编译器会为我们提供一个合成默认构造函数,当我们创建对象的时候,调用合成默认构造函数。默认构造函数无任何实参如果我们显式的定义了一个默认构造函数,则当我们创建对象的时候,如果没有传递任何参数,那么调用默认构造函数。3.合成默认构造函数初始化类的成员的规则:- 如果存在类内初始值,用它来初始化成员- 如果没有类内初始值原创 2021-10-10 17:00:44 · 155 阅读 · 0 评论 -
C++深入学习笔记(11)——const成员函数
我们知道,在C++类中,this指针是一个指向非常量类型的常量指针,也就是说我们可以通过this指针来访问类的成员变量并对其进行修改,那么如果我们要用this指向一个常量对象该怎么办? 尽管this指针是隐式的,但是它仍然需要遵循初始化规则,因此我们不能用this指针指向一个常量对象,所以我们应该把this指针设置成指向常量的常量指针。 然而this是隐式的,不会出现在参数列表中,因此C++语言的做法就是把const关键字放在成员函数的参数列表之后,此时,紧跟在参数列表之后的const表示this指针.原创 2021-10-10 15:32:09 · 93 阅读 · 0 评论 -
C++深入学习笔记(10)——函数指针
函数指针指向的是函数而非对象。原创 2021-09-01 15:33:19 · 77 阅读 · 0 评论 -
C++深入学习笔记(9)——函数匹配
函数匹配主要发生在函数重载的调用中。 当几个重载函数的形参数量以及形参的类型可以由其它类型转换得来时,这时我们就要分析函数是怎么匹配的了。我们上代码。#include<iostream>using namespace std;void f();void f(int);void f(int, int)void f(double, double a = 1.230);int main(){ f(5.6);}void f(){...原创 2021-09-01 12:57:40 · 210 阅读 · 0 评论 -
C++深入学习笔记(8)——返回值
1 值是如何被返回的返回一个值的方式和初始化一个变量或形参的方式完全一样,返回的值用于初始化调用点的一个临时量,该临时量就是函数的调用结果 同其w他引用类型一样,如果函数返回引用,则该引用仅是它所引对象的一个别名。const string &FindLargest(const string &str1, const string &str2){ return str1.size() > str2.size()? str1 :...原创 2021-08-25 14:12:18 · 469 阅读 · 0 评论 -
C++深入学习笔记(7)——含有可变形参的函数
有时候我们无法提前预支应该向函数传递几个参数。例如,我们想要编写代码输出程序产生的错误信息,此时最好用同一个函数实现该功能,一遍对所有错误的处理能够整齐划一。然而,由于错误信息的种类不同没所以调动错误输出函数时传递的实参也各不相同。1.initializer_list形参 如果函数的实参数量未知但是全部实参的类型都相同,我们可以使用initialist_list类型的形参。initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。它定义在同名的头文件中。1....原创 2021-08-25 13:20:06 · 153 阅读 · 0 评论 -
C++深入学习笔记(6)——类型转换
C++风格的类型转换比C风格的类型转换写法不同,而且更加的细致。命名的强制类型转换格式:cast-name<type>(expression)其中,type是要转换成的类型。expression是要进行转换的表达式。cast-name是转换方式的名字,分为static_cast、const_cast、reinterpret_const1.static_cast任何具有明确定义类型的类型转换,只要不包含底层const,都可以使用static_castint a = 6, b原创 2021-08-24 13:57:49 · 70 阅读 · 0 评论 -
C++深入学习笔记(5)——多维数组
严格来说,C++语言中没有多维数组,多维数组其实是数组的数组。1.多维数组的初始化正如我们所说的,多维数组其实是数组的数组,那么就可以理解成,一个元素数量为m的数组,它的元素为元素数量为n的数组。那么可以显式地初始化它。int array[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} ...原创 2021-08-24 13:19:14 · 245 阅读 · 0 评论 -
C++深入学习笔记(4)——处理类型
一、类型别名 类型别名是一个名字,它是某种类型的同义词。 类型别名有两种方法定义。传统的方法是使用typedeftypedef int DataType; // DataType是int的同义词typedef struct SLinkList{ DataType data; struct SLinkList *next;}SLinkList, *SLinkListPtr; // SLinkList是struct SL...原创 2021-08-01 20:25:16 · 114 阅读 · 0 评论 -
C++深入学习笔记(3))——const和constexpr
一、const的引用 我们可以把引用绑定到const对象上,就像是对其它的对象引用一样。我们称之为对常量的引用。然而,对常量的引用不能修改被引用对象的值。const int a = 10;const int &b = a; // 正确:引用和被引用对象都是常量b = 1; // 错误:试图修改被引用的常量对象的值int &c = a; // 错误:试图让一个非常量对象引用一个常量对象 第四个因为不能对a...原创 2021-07-31 21:26:03 · 142 阅读 · 0 评论 -
C++深入学习笔记(2)——变量声明和定义
声明使得名字为程序所知,一个文件如果想使用其它文件定义的名字,则必须包含对那个名字的声明。定义负责创建与名字相关联的实体。 变量声明规定了变量的类型和名字,这一点与定义相同。但是定义还申请了内存空间,也会为声明的变量赋予一个初始朱。 如果想声明一个变量而非定义它,就得在变量名前加一个extern,而且不要显式地初始化它。extern int i; // 声明一个int型变量i(无初始化)int i; // 声明并且定义一...原创 2021-07-30 16:36:33 · 312 阅读 · 0 评论 -
C++深入学习笔记(1)——初始化
当对象在创建的时候获得了一个特定的值,称这一对象被初始化。用于初始化变量的值可以是任意复杂的表达式。被初始化过后的变量可以去初始化定义其它变量。 在C++语言中,初始化是个异常复杂的问题。初始化和赋值是两个完全不同的操作,至少在C++中是如此的,虽然在C++中优势这种区别无关紧要。初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象当前的值擦除,并且用一个新的值来替代。一、列表初始化 C++语言定义了初始化的好几种不同的形式,...原创 2021-07-30 16:18:21 · 354 阅读 · 0 评论