头文件资料库
# include<iostream>
这是最常用的头文件,在C++中,#include <iostream>
是一条预处理指令,用于包含标准库中的 iostream
头文件。iostream
是C++标准库的一部分,主要用于输入和输出操作。
以下是 iostream
头文件的一些主要特点和组件:
标准流对象:
cin
:标准输入流,通常用于从键盘读取输入。cout
:标准输出流,用于向屏幕输出数据。cerr
:标准错误流,用于输出错误消息到屏幕,不经过缓冲区,直接输出。clog
:类似于cerr
,但输出通过缓冲区,用于输出日志信息。
输入/输出操作符:
>>
:从cin
读取数据的提取操作符。<<
:向cout
,cerr
, 或clog
写入数据的插入操作符。
操纵符:用于改变流的格式或行为的函数,如
endl
(用于插入换行符并刷新输出缓冲区)、std::setw
(设置字段宽度)、std::setprecision
(设置浮点数的精度)等。流状态标志:用于检查和设置流的状态(如错误状态)的功能。
iostream
头文件非常重要,因为它提供了与用户交互的基本机制。例如,它使得从标准输入读取数据以及将数据输出到标准输出成为可能,这对于控制台程序来说非常关键。
一个基本的使用 iostream
的示例:
#include <iostream>
using namespace std;
int main() {
int number;
cout << "Enter a number: ";
cin >> number;
cout << "You entered " << number << endl;
return 0;
}
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
在这个程序中,我们使用 cin
来从用户那里接收一个数字,并使用 cout
来输出这个数字。endl
用于在输出的末尾添加一个换行符,并刷新输出缓冲区,确保立即显示输出。
# include<vector>动态数组
在C++标准模板库(STL)中,<vector>
头文件提供了 std::vector
类,这是一个动态数组的实现。std::vector
是一种序列容器,它可以存储具有相同类型的元素,并支持随机访问。
以下是 std::vector
的一些主要特点:
动态数组:
vector
的大小可以在运行时动态改变。它可以根据需要自动扩容和缩容。连续存储:
vector
中的元素是在连续的内存空间中存储的,这意味着它支持快速的随机访问。操作:
push_back
:在vector
的末尾添加一个元素。pop_back
:移除vector
末尾的元素。insert
:在指定位置插入一个或多个元素。erase
:删除指定位置或范围内的元素。clear
:移除所有元素,使vector
为空。size
:返回vector
中的元素数量。resize
:改变vector
的大小。[]
运算符和at
方法:用于访问vector
中的元素。
性能特点:
- 插入和删除操作在
vector
的末尾是高效的,但在中间或开始位置可能需要移动元素,因此可能较慢。 - 提供高效的随机访问,即直接访问任何位置的元素。
- 当
vector
的容量不足以容纳更多元素时,会自动重新分配更大的内存空间来扩容,这个操作的时间复杂度是线性的。
- 插入和删除操作在
用途:适用于需要快速随机访问元素的场景,以及元素的添加和移除主要发生在序列的末尾。
在使用 std::vector
时,你需要包含 <vector>
头文件。由于 vector
是模板类,你可以用它来存储任何类型的元素,例如 std::vector<int>
、std::vector<std::string>
等。
std::vector
是最常用的 STL 容器之一,因为它提供了高度灵活的数据结构,同时具备数组的许多优点。在实际编程中,vector
通常是默认的序列容器选择,除非有特定的理由要求使用其他类型的容器。
# include<deque>
双端队列
deque
在C++标准模板库(STL)中的全称是 "Double-Ended Queue",即双端队列。它是一种允许在容器两端(即头部和尾部)高效插入和删除元素的序列容器。
deque
的特点包括:
- 提供对头部和尾部元素的快速访问。
- 支持在头部和尾部高效地插入和删除元素。
- 支持随机访问,即可以通过索引直接访问任何元素。
- 内部实现通常比
vector
复杂,因此当只需要在尾部添加或删除元素时,vector
可能是更好的选择。
由于 deque
提供了在两端操作的灵活性,它在需要这种特性的场景下非常有用,如在实现某些算法或数据结构(例如队列和广度优先搜索算法)时。
# include<list>
链表
在C++标准模板库(STL)中,<list>
头文件提供了 std::list
容器类,这是一个双向链表的实现。std::list
允许快速的插入和删除操作,它主要用于那些需要频繁插入和删除元素,且不需要快速随机访问的场合。
以下是 std::list
的一些主要特点:
动态大小:与数组不同,
list
的大小不是固定的,可以根据需要动态增长或缩减。非连续存储:
list
中的元素不是连续存储的,而是通过指针链接在一起。这意味着它允许常数时间内的元素插入和删除,但不支持快速随机访问。双向迭代:
list
提供双向迭代,你可以从头到尾或从尾到头遍历列表。操作:
push_front
和push_back
:在列表的前端或后端添加一个元素。pop_front
和pop_back
:从列表的前端或后端移除一个元素。insert
:在指定位置插入一个或多个元素。erase
:删除指定位置或范围内的元素。clear
:移除所有元素,使列表为空。size
:返回列表中的元素数量。sort
:对列表元素进行排序。reverse
:反转列表中元素的顺序。
性能特点:
- 插入和删除操作通常是常数时间复杂度,与列表的大小无关。
- 由于元素不是连续存储的,遍历
list
比遍历vector
或数组要慢。 - 不支持通过索引直接访问元素。
用途:适用于元素经常被插入或删除,且不需要快速随机访问的场景。
在使用 std::list
时,你需要包含 <list>
头文件。由于 list
是模板类,你可以用它来存储任何类型的元素,例如 std::list<int>
、std::list<std::string>
等。
在选择容器类型时,了解不同容器的特点和适用场景非常重要。对于需要快速随机访问的场合,std::vector
或数组可能是更好的选择;而对于频繁的插入和删除操作,特别是在序列的两端,std::list
或 std::deque
更为合适。
# 如何自己编写头文件
头文件是可以自定义的,在C++中,头文件通常用于声明函数、类、模板和全局变量等,这样它们就可以在多个源文件中被重用。头文件有助于组织代码、提高可维护性,并促进模块化编程。
创建头文件的基本步骤如下:
# 1. 创建头文件
创建一个扩展名为 .h
或 .hpp
的文件。例如,my_functions.h
。
# 2. 写入代码
在头文件中,您可以包含如下内容:
- 函数原型(声明)
- 类定义
- 模板定义
- 全局变量的声明
- 宏定义
- 其他头文件的包含
例如,一个简单的头文件可能包含一个函数的声明:
// my_functions.h
#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H
void PrintHelloWorld();
#endif // MY_FUNCTIONS_H
2
3
4
5
6
7
2
3
4
5
6
7
# 3. 使用头文件防护
为了防止头文件内容在同一个编译单元中被包含(#include
)多次,通常使用预处理指令 #ifndef
、#define
和 #endif
来创建所谓的 "include guards"。在上面的例子中,MY_FUNCTIONS_H
就是一个守卫宏。
# 4. 在源文件中包含头文件
在您的 .cpp
源文件中,使用 #include "my_functions.h"
来包含并使用头文件中声明的内容。
// main.cpp
#include <iostream>
#include "my_functions.h"
void PrintHelloWorld() {
std::cout << "Hello, World!" << std::endl;
}
int main() {
PrintHelloWorld();
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
在上面的例子中,PrintHelloWorld
函数在 my_functions.h
中声明,在 main.cpp
中定义,并在 main
函数中调用。
# 5. 编译
编译您的程序时,确保包含所有相关的 .cpp
文件。头文件本身不会被直接编译,但它们在预处理阶段被包含在源文件中。
创建和使用自定义头文件是一种很好的实践,尤其是在较大的项目中,因为它有助于将声明和实现分离,使代码更清晰、更易于管理。
# 6. 路径管理
前面没有提到路径如何管理,这也是确保头文件起作用很重要的一步。
在C++中,包含(或导入)头文件时,头文件的路径可以根据其相对于源文件的位置或是相对于编译器的搜索路径来指定。头文件的路径可以用双引号 ""
或尖括号 <>
来指定,两者在搜索路径上有所不同。
# 使用双引号 ""
当使用双引号包含头文件时,如 #include "my_header.h"
,编译器首先在源文件的当前目录中查找头文件。如果在当前目录中没有找到,它将按照编译器的搜索路径继续查找。这通常用于你自己编写的头文件或者特定于项目的头文件。
例如:
#include "my_header.h" // 查找当前目录下的my_header.h
# 使用尖括号 <>
当使用尖括号包含头文件时,如 #include <iostream>
,编译器直接在其标准库目录和其他配置的库目录中搜索头文件。这主要用于标准库头文件或第三方库头文件。
例如:
#include <iostream> // 查找标准库中的iostream
# 指定头文件路径
如果头文件不在当前目录或标准库路径中,你需要告诉编译器去哪里查找这些文件。这可以通过以下几种方式实现:
使用相对路径: 如果头文件位于源文件所在目录的子目录中,可以使用相对路径。
#include "subdir/my_header.h" // 在子目录中查找
11使用绝对路径: 直接指定头文件的完整路径(不推荐,因为降低了代码的可移植性)。
#include "/path/to/my_header.h"
11编译器的 include 路径: 在编译时,可以通过编译器的命令行选项指定额外的 include 路径。例如,对于 GCC 和 Clang,可以使用
-I
选项。g++ -I/path/to/headers my_program.cpp
11这告诉编译器在
/path/to/headers
目录中也查找头文件。
# 小提示
保持项目的组织结构清晰,将头文件放在合适的目录中,可以避免很多关于路径的问题。对于较大的项目,通常有一个专门的目录(如 include
)来存放所有头文件。