基础概念以及和C有区别的部分在(1)、(2)都进行了学习,下面花一些篇幅梳理细碎的知识点。

C++数字

数字定义很简单,使用原始的数据类型定义即可。

C++数字运算

C++中的数学运算,都写在标准C和C++库中,叫做内置函数,若是需要使用这些内置函数,需要引用对应的头文件

C++随机数

在许多情况下需要生成随机数,主要函数是rand(),生成一个伪随机数,生成随机数之前需要先调用一下srand()函数。

C++数组

数组其实在C中用的很多,并不陌生,可以存储一个固定大小的顺序集合,数组一般是由连续的内存位置组成,最低的地址对应第一个元素,最高的地址对应最后一个元素。

数组的声明和C一致,类型 数组名[number]。

数组的初始化:可以使用一个初始化语句,或者省略掉数组的大小,若是选择省略,数组的大小就是初始化时数组的大小。

访问数组

数组元素可以通过数组名称加索引进行访问,索引一般放在方括号内,跟在数组的后边。

C++中的数组是非常重要的,下面是一些数组的重要概念:

多维数组:最简单的形式是二维数组。

指向数组的指针:通过指定不带索引的数组名称来生成指向数组第一个元素的指针。

传递数组给函数:通过指定不带索引的数组名称来给函数传递一个指向数组的指针。

从函数返回数组:C++允许从函数返回数组。

C++字符串

表示形式:同C或者C++中引入了string类类型。

C风格的字符串无需叙述,字符数组,以null字符’\0’终止,编译器会在初始化数组时,自动把 \0 放在字符串的末尾。

与数值计算类似,C++中也有大量的函数用来操作以null结尾的字符串。

C++中的string类

在C++的标准库中提供了string类类型,除了以上的功能之外,还额外增加了许多功能。

其实就是将原来的一些函数给进行了封装变成了一个class,这样调用的时候就会变得易用且移植性更好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>

using namespace std;

int main ()
{
string str1 = "runoob";
string str2 = "google";
string str3;
int len ;

// 复制 str1 到 str3
str3 = str1;
cout << "str3 : " << str3 << endl;

// 连接 str1 和 str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;

// 连接后,str3 的总长度
len = str3.size();
cout << "str3.size() : " << len << endl;

return 0;
}

C++指针

指针的大体概念和C其实没多少的差异,所有的数据类型的指针都是一样的,不同的只是指向的数据类型不同而已。

每一个变量都有内存位置,每个位置都有自己的地址,可以使用&进行访问。

C++使用指针

同C

C++指针详解

Null指针:空指针,是一个定义在标准库中的值为零的常量。

指针运算:++、–、+、-。

指针和数组:指针和数组有着密切的关系。

指针数组:定义用来存储指针的数组,int* p[5],p中存储着5个指向整形数据的指针。

指向指针的指针:在C++中是允许的。

传递指针给函数。

函数返回指针。

C++引用

相较于指针,C++中区别于C的一个概念就是引用,引用变量是一个别名,是已存在变量的另一个名字,可以指向变量,说到这就很容易和指针混淆在一起。

指针 vs 引用

1.不存在空引用,引用必须连接到一块合法的内存。

2.一旦引用初始化为一个对象,就不能指向另外一个对象,而指针在任何时候都可以指向另一个对象。

3.引用必须在被创建时初始化,指针可以在任何时候被初始化。

C++创建引用

1
2
3
int i = 17;
int& m = i;
double& n = j;

引用和指针一样,也常被使用于函数的参数列表和函数返回值。

C++日期&时间

C++主要是继承了C用于日期和时间操作的结构和函数,常规所用的都在标准库当中,不过多赘述。

C++基本输入输出

标准库提供了一组丰富的输入/输出功能,C++的io发生在流中,流是字节序列,流向内存则称为输入操作,若是从内存流向设备,叫做输出。

标准输出流cout

预定义的对象cout是iostream类的一个实例,cout对象连接到标准输出设备,一般是显示屏,和<<结合使用。<<叫做流插入运算符,流插入运算符可以在一个语句多次使用。

标准输入流cin

预定义的对象cin是iostream类的一个实例,cin对象附属到标准输入设备,通常是键盘,一般和流提取运算符>>结合使用。

1
2
3
4
cin >> name >> age;
cin >> name;
cin >> age;
//以上等价

标准错误流cerr

cerr也是iostream类的一个实例,附属于输出设备,但其是非缓冲的,会立即输出,搭配 << 使用。

标准日志流clog

与cerr不同的是,clog对象是缓冲的,每个流插入到clog都会先存储在缓冲区,等到填满或者刷新才输出。

这样分类的好处就是当出现错误的时候,可以立即就知道,而常规运行的输出可以记录在日志当中。

C++结构体

数组是可以存储相同类型数据项的变量,那么结构体就是可以用户自定义的数据类型,允许存储不同类型的数据项,表面来看,结构体和类比较类似,允许定义成员变量和成员函数,定义需要使用struct语句:

1
2
3
4
5
6
7
struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;

结构体的优点:

1.适合封装多种简单数据,用于数据的存储。

2.相比于class,语法更为简单,适合小型数据对象。

3.支持构造函数,成员函数和访问权限控制,可以实现面向对象。

访问结构体成员

我们一般使用成员访问运算符(.),该符号是结构体变量名称和我们要访问成员之间的一个符号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <cstring>

using namespace std;

struct Books{
char title[50];
char author[50];
char subject[100];
int book_id;
};

int main(){
Books Book1;
Books Book2;

strcpy(Book1.title, "C++ 教程");
strcpy(Book1.author, "Dongzh");
strcpy(Book1.subject, "Code lanuage");
Book1.book_id = 123456;
}

结构体作为函数参数

结构体作为函数参数和其他类型变量或指针类似,和正常访问无异。

结构体虽然在功能上类似于类,但是在细节部分还是有一些不同的,如在访问权限,结构体也是可以使用public、private和protected来定义成员的访问权限,在结构体中,默认权限为public,但是在class中,默认是private。

指向结构体的指针

1
struct Books *strcut_pointer;

与其他类型的指针类似,查找结构体的地址使用&运算符放在结构体的前面:

1
strcut_pointer = &Book1;

若是需要使用指针来访问结构体的成员,则需要使用->运算符:

1
struct_pointer->title;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>

using namespace std;

// 声明一个结构体类型 Books
struct Books
{
string title;
string author;
string subject;
int book_id;

// 构造函数
Books(string t, string a, string s, int id)
: title(t), author(a), subject(s), book_id(id) {}
};

// 打印书籍信息的函数
void printBookInfo(const Books& book) {
cout << "书籍标题: " << book.title << endl;
cout << "书籍作者: " << book.author << endl;
cout << "书籍类目: " << book.subject << endl;
cout << "书籍 ID: " << book.book_id << endl;
} //参数是通过引用进行传递,避免不必要的拷贝。

int main()
{
// 创建两本书的对象
Books Book1("C++ 教程", "Runoob", "编程语言", 12345);
Books Book2("CSS 教程", "Runoob", "前端技术", 12346);

// 输出书籍信息
printBookInfo(Book1);
printBookInfo(Book2);

return 0;
}

typedef关键字

利用typedef关键字可以为创建的类型取一个别名:

1
2
3
4
5
6
typedef struct Books{
char title[50];
char author[50];
char subject[100];
int book_id;
}Books;

这样就可以使用Books来定义Books类型的变量,而不需要struct关键字。

C++vector容器

C++中的vetcor是一种序列容器,允许在运行的时候动态的插入和删除元素,vector是基于数组的数据结构,但vector可以自动管理内存,不用手动分配和释放,相较数组来说,vector具有更多的灵活性和功能。

vector还是C++标准模板库的一部分,具有灵活的接口和操作,使用vector需要我们包含头文件。

创建vector

1
std::vector<int> myvector;	//创建一个存储整数的空vector

创建时也可以指定初始大小和初始值。

1
std::vector<int> vec2 = {1, 2, 3, 4};

添加元素:使用push_back()方法,可以将元素添加到vector末尾。

访问元素:使用下标操作符[]和at()方法访问vector中的元素。

获取大小:使用size()方法获取vector中元素的数量。

迭代访问:使用迭代器遍历vector中的元素。

1
2
3
4
5
6
7
for (auto it = myvector.begin(); it != myvector.end(); ++it){
std::cout << *it << " ";
} //迭代器进行遍历

for (int element : myvector){
std::cout << element << " ";
} //使用范围循环

删除元素:使用erase()方法可以进行删除。

清空vector:使用clear()方法可以对vector进行清空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <vector>

int main() {
// 创建一个空的整数向量
std::vector<int> myVector;

// 添加元素到向量中
myVector.push_back(3);
myVector.push_back(7);
myVector.push_back(11);
myVector.push_back(5);

// 访问向量中的元素并输出
std::cout << "Elements in the vector: ";
for (int element : myVector) {
std::cout << element << " ";
}
std::cout << std::endl;

// 访问向量中的第一个元素并输出
std::cout << "First element: " << myVector[0] << std::endl;

// 访问向量中的第二个元素并输出
std::cout << "Second element: " << myVector.at(1) << std::endl;

// 获取向量的大小并输出
std::cout << "Size of the vector: " << myVector.size() << std::endl;

// 删除向量中的第三个元素
myVector.erase(myVector.begin() + 2);

// 输出删除元素后的向量
std::cout << "Elements in the vector after erasing: ";
for (int element : myVector) {
std::cout << element << " ";
}
std::cout << std::endl;

// 清空向量并输出
myVector.clear();
std::cout << "Size of the vector after clearing: " << myVector.size() << std::endl;

return 0;
}

C++的数据结构

C++中有许多数据结构,基础的如数组、结构体、类等,高级的如STL容器如vector、map和unordered_map。

1.数组:

存储相同类型的一组数据。

2.结构体:

允许将不同类型数据组合在一起,形成自定义的数据类型。

3.类(class):

面向对象编程的核心,允许定义成员变量和成员函数,和struct类似,但是功能更加强大,支持继承、封装、多态,同时包含构造函数和析构函数。

1
2
3
4
5
6
7
8
9
10
11
12
class Person {
private:
string name;
int age;
public:
Person(string n, int a) : name(n), age(a) {}
void printInfo() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
Person p("Bob", 30);
p.printInfo(); // 输出: Name: Bob, Age: 30

4.链表:

一种动态数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。可以调整大小,不需要提前定义容量,操作效率高。

1
2
3
4
5
6
7
8
struct Node{
int data;
Node* next;
};

Node* head = nullptr;
Node* newnode = new(10, nullptr);
head = newnode;

5.栈:

栈是先进后出的数据结构,常用于递归和深度优先搜索等场景,只允许在栈顶进行对应的操作。

1
2
3
4
5
stack<int> s;
s.push(1);
s.push(2);
std::cout << s.top() << endl;
s.pop();

6.队列:

队列是先进先出的数据结构,用于广度优先搜索,任务调度场景,插入在队尾进行,删除在队头进行。

1
2
3
4
5
queue<int> q;
q.push(1);
q.push(2);
cout << q.front();
q.pop();

7.双端队列:

允许在两端进行插入和删除操作数据结构,是栈和队列的结合体。

1
2
3
4
5
deque<int> dq;
dq.push_back(1);
dq.push_front(2);
cout << dq.front();
dq.pop_front();

适合需要在两端频繁操作的场景。

8.哈希表:

一种通过无序键值对存储数据的结构,支持快速查找、插入和删除操作,unordered_map是哈希表的实现。

1
2
3
unordered_map<string, int> hashtable;
hashtable["apple"] = 10;
cout << hashtable["apple"]; //输出10

除了unordered_map之外,unordered_set也是哈希表的实现之一,使用哈希函数快速定位元素,但是不保证元素的顺序。

9.映射:

一种有序的键值对容器,底层实现是红黑树,和哈希表不同,映射保证键的顺序,使用二叉搜索树实现。

1
2
3
map<string, int> mymap;
mymap["apple"] = 10;
cout << mymap["apple"];

适合需要按照顺序处理数据的场景。

10.集合:

一种用于存储唯一元素的有序集合,保证元素不重复且有序。

1
2
3
4
set<int> s;
s.insert(1);
s.insert(2);
cout << *s.begin(); // 输出 1

11.动态数组:

一种标准库的实现,可以动态扩展容量,支持随机访问。

1
2
3
4
vector<int> v;
v.push_back(1);
v.push_back(2);
cout << v[0]; // 输出 1

下面就要学习类和对象的知识。