1. C++标准库

C++提供了很多库:

  1. 标准 ANSI C 库都可以移植到 C++中。不同于 ANSI C 库的是,C++中需要在库名前加上"c"前缀,而且去掉".h",例如<cmath>对应于 C 语言就是<math.h><cstdlib>对应于 C 语言的<stlib.h>
  2. C++新增的库,例如 <iostream><iomanip><string><fstream><sstream>
  3. C++STL:包括容器,迭代器,算法和函数对象
  4. Boost C++库

1.1 C 库和相关头文件

  • <cstring>:待会解释
  • <cmath>:数学计算相关的库
  • <cstdlib>:通用工具,例如异常(abort, exit, EXIT_SUCCESS, EXIT_FAILURE);环境相关(getenv);动态内存管理(malloc, free, calloc, realloc),字符解析(atoi, atof, atol, strtod), 伪随机序列生成(rand, srand, RAND_MAX);数组搜索和排序(bsearch, qsort)
  • <cctype>:字符类型检测(isalpha, isdigit, isalnum, isspace, isupper, islower, isblank, iscntrl, isgraph, isprint, ispunct, isxdigit)和字符转换(toupper, tolower)
  • <climits>, <cfloat>:Size and limit of integer types (INT_MAX, INT_MIN, UINT_MAX, CHAR_BIT; and SHRT_XXX for short, LONG_XXX for long, LLONG_XXX for long long, CHAR_XXX for char) and floating-point types (DBL_MIN, DBL_MAX, DBL_DIG, DBL_MIN_EXP, DBL_MAX_EXP; and FLT_XXX for float, LDBL_XXX for long double)
  • <ctime>:time, difftime, clock, gmttime, localtime, and etc.
  • <cstdio>: C’s IO operations (scanf, printf, fscanf, fprintf, fopen, fclose, etc)
  • <cassert>, <cerrno>, csignal>: 断言和错误
  • <clocale>:本地化
  • <cstdbool>, <cstdint>, <cstddef>, <cstdarg>:
  • <cuchar>, <cwchar>, <cwcchar>: Unicode 字符

1.2 C++库和相关头文件

  • <ios>, <iostream>, <istream>, <ostream>, <fstream>, <sstream>
  • <iomanip>
  • <string>
  • <regex>
  • <random>
  • <limits>
  • <stdexception>, <exception>
  • <complex>, <tuple>, <valarry>
  • <locale>
  • <typeinfo>
  • <chrono>
  • 其它:<codecvt>, <new>, <ratio>, <system_error>, <type_traits>

1.3 C++ STL 和相关头文件

STL 主要由以下头文件提供:

  • <vector>, <list>, <deque>, <queue>, <stack>, <map>, <set>, <bitset>, <forward_list> (C++11), <unordered_map> (C++11), <unordered_set> (C++11), <array> (C++11):容器和数据结构模板类
  • <iterator>:迭代器
  • <algorithm>, <numeric>, <functional>, <utility>:算法和函数对象
  • <initializer_list> (C++11), <memroy> (C++11)

1.4 Boost C++库

  • TODO

2. C++ STL

2.1 初探 C++ STL 中的 vector 类

示例 1:构造vector<>和访问元素

 1#include <iostream>
 2#include <cstdlib>
 3#include <ctime>
 4#include <vector>
 5
 6using namespace std;
 7
 8
 9void print(const vector<int> &v) {
10	for (int i = 0; i < v.size(); ++i) {
11		cout << v[i] << " ";
12	}
13	cout << endl;
14}
15
16int main(int argc, char *argv[]) {
17	const int SIZE = 10;
18	vector<int> numbers(SIZE);
19
20	cout << "size = " << numbers.size() << endl;
21	cout << "capacity = " << numbers.capacity() << endl;
22	print(numbers);
23
24	srand(time(0));
25
26	for (size_t i = 0; i < numbers.size(); ++i) {
27		numbers.at(i) = rand() % 100;
28	}
29
30	print(numbers);
31
32	// no error compile and run
33	cout << "First element is " << numbers.front() << endl;
34	// runtime out_of_range exception
35	cout << "Last element is " << numbers.back() << endl;
36
37	cout << numbers[55] << endl;
38	// cout << numbers.at(55) << endl;
39
40	return 0;
41}

特别说明:

size 是当前 vector 容器真实占用的大小,也就是容器当前拥有多少个容器。

capacity 是指在发生 realloc 前能允许的最大元素数,即预分配的内存空间。

示例 2:使用push_back()pop_back()来添加和删除元素

 1#include <iostream>
 2#include <cstdlib>
 3#include <ctime>
 4#include <vector>
 5
 6using namespace std;
 7
 8void print(const vector<int> &v) {
 9	for (int i = 0; i < v.size(); ++i) {
10		cout << v[i] << " ";
11	}
12	cout << endl;
13}
14
15int main(int argc, char *argv[]) {
16	vector<int> numbers;
17	cout << "size = " << numbers.size() << endl;
18	cout << "capacity = " << numbers.capacity() << endl;
19
20	srand(time(0));
21	for (int i = 0; i < 5; ++i) {
22		numbers.push_back(rand() % 100);
23	}
24	print(numbers);
25	cout << "size = " << numbers.size() << endl;
26	cout << "capacity = " << numbers.capacity() << endl;
27
28	numbers.pop_back();
29	numbers.pop_back();
30	print(numbers);
31	cout << "size = " << numbers.size() << endl;
32	cout << "capacity = " << numbers.capacity() << endl;
33	numbers.clear();
34	cout << "size = " << numbers.size() << endl;
35	cout << "capacity = " << numbers.capacity() << endl;
36	return 0;
37}

示例 3:使用iterator来访问容器元素

 1#include <iostream>
 2#include <string>
 3#include <cstdlib>
 4#include <vector>
 5
 6using namespace std;
 7
 8void print(vector<string> &v) {
 9	for (vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter) {
10		cout << *iter << " ";
11	}
12	cout << endl;
13}
14
15int main(int argc, char *argv[]) {
16	vector<string> strs;
17	strs.push_back("apple");
18	strs.push_back("orange");
19	strs.push_back("banana");
20	print(strs);
21	cout << "size = " << strs.size() << endl;
22
23	// Test insert()
24	strs.insert(strs.begin() + 2, "b4-banana");
25	strs.insert(strs.begin() + 1, 2, "b4-orange");
26	print(strs);
27
28	// Test arase()
29	strs.erase(strs.begin() + 1, strs.begin() + 4);
30	print(strs);
31	cout << "size + " << strs.size() << endl;
32
33	// insert() from another vector
34	vector<string> newStrs;
35	newStrs.push_back("1");
36	newStrs.push_back("2");
37	newStrs.push_back("3");
38	strs.insert(strs.begin() + 1, newStrs.begin(), newStrs.end());
39	print(strs);
40	cout << "size = " << strs.size() << endl;
41	return 0;
42}

说明:

  • 每一种容器类都有其对应的迭代器
  • vectorbegin()end()成员函数分别返回一个指向集合第一个元素的iterator和指向最后一个元素后的iterator
  • Iterator 很像指针,可以使用*iter来访问元素,++iter来移动到下一个元素
  • insert(iter, item),在当前 iter 元素前插入 item,insert(iter, n , item),在当前 iter 前插入 n 个 item
  • erase(first, last),删除区间$[first, last)$中的所有元素
  • 在 C++11 中可以使用auto来作为 iterator 的类型,从而告诉编译器自动匹配类型:
1for (auto iter = strs.begin(); iter != strs.end(); ++iter) {
2	cout << *iter << " ";
3}
  • C++引入了一种 for-each 循环
1for (auto item:strs) {
2	cout << item << " ";
3}

2.2 vector 模板类

Constructor

 1vector (const allocator_type & alloc = allocator_type());
 2   // Default Constructor: construct a vector object
 3vector (size_type n, const value_type & val = value_type(),
 4        const allocator_type & alloc = allocator_type());
 5   // Fill Constructor: construct a vector object with n-element filled with val
 6vector (const vector & v);
 7   // Copy Constructor
 8template <class InputIterator>
 9vector (InputIterator first, InputIterator last,
10        const allocator_type & alloc = allocator_type());
11   // Range Copy Constructor

Size and Capacity

1size_type size () const;      // Return the size (number of elements)
2size_type capacity () const;  // Return the storage allocated (in term of element)
3bool empty () const;          // Return true if size is 0
4void reserve (size_type n);   // Request for storage to hold n elements
5void resize (size_type n, value_type val = value_type());
6      // resize to n, remove extra element or fill with val
7size_type max_size () const;  // Return the maximum number of element
8void shrink_to_fit ();        // (C++11) Request to shrink storage

Accessing Element

1value_type & operator[] (size_type n);  // [n] operator (without index-bound check)
2value_type & at (size_type n);          // Return a reference to n-th element with index-bound check
3value_type & front ();    // Return a reference to the first element
4value_type & back ();     // Return a reference to the last element

Modifying Contents

1void push_back (const value_type & val); // Append val at the end
2void pop_back ();                        // Remove the last element
3void clear ();                           // Remove all elements

Non-member Friend Functions

 1==, !=, <, >, <=, >=    // Comparison Operators
 2// E.g.
 3template <class T, class Alloc>
 4bool operator== (const vector<T,Alloc> & left, const vector<T, Alloc> & right);
 5   // Compare two vectors
 6   // For == and !=, first compare the size, then each element with equal algorithm.
 7   //   Stop at the first mismatch.
 8   // For <, >, <=, >=, use lexicographical_compare algorithm. Stop at first mismatch.
 9
10template <class T, class Alloc>
11void swap (vector<T,Alloc> & v1, vector<T,Alloc> v2);
12   // Swap the contents of containers v1 and v2.
13   // Both shall has the same type, but can have different sizes.

Iterator

1iterator begin();  // Return an iterator pointing to the first element
2iterator end();    // Return an iterator pointing to the pass-the-end element
3
4reverse_iterator rbegin(); // Return a reverse iterator pointing to the reverse beginning (last element)
5                           // increasing a reverse iterator to transverse in reverse order
6reverse_iterator rend();   // Return a reverse iterator pointing to the reverse past-the-end

Iterator-based Operations

 1iterator insert (iterator pos, const value_type & val);  // Single-Element: insert element val before iterator pos
 2void     insert (iterator pos, size_type n, const value_type & val);  // Fill: insert n copies of val before pos
 3template <class InputIterator>
 4void     insert (iterator pos, InputIterator first, InputIterator last)
 5    // Range-copy: copy the range [first, last) and insert before pos.
 6
 7iterator erase (iterator pos);  // Single-element: remove element pointed to by iterator pos
 8iterator erase (iterator first, iterator last);  // Range: remove elements between [first,last)
 9
10void assign (size_type n, const value_type & val);  // Fill: clear old contents and assign n copies of val
11template <class InputIterator>
12void assign (InputIterator first, InputIterator last);  // Range: assign [first, last)

2.3 容器

顺序型容器,关联型容器和容器适配器

STL 提供了以下几种类型的容器:

顺序型容器:元素是线性结构组织的

  • vector: dynamically resizable array.
  • deque: double-ended queue.
  • list: double-linked list.

关联型容器:存储 key-value 对的非线性结构

  • set: 没有重复元素,支持快速查找
  • multiset: 允许重复元素,支持快速查找
  • map: 一对一隐射(关联数组),没有重复元素,支持快速 key 查找
  • multimap: 一对一隐射,允许有重复元素,支持快速 key 值查找

容器适配器类:

  • Stack: 后进先出
  • queue: 先进先出
  • priority_queue: 高优先级的位于队列前面