(1)C++primer:总结
《C++ Primer 第五版》是 C++ 领域的经典教材,全面覆盖了 C++11 标准的核心特性,兼顾语法细节与编程实践,既适合初学者入门,也适合有经验开发者查漏补缺。
以下从基础概念、核心特性、容器与算法、高级主题四个维度,提炼全书核心知识点。
后续会进行单一详细讲解。
目录
第一章 开始
第二章 变量和基本类型
第三章 字符串 向量 数组
第四章 表达式
第五章 语句
第六章 函数
第七章 类
第八章 IO库
第九章 顺序容器
第10章 泛型算法
第11章 关联容器
第12章 动态内存
第13章 拷贝控制
第14章 重载运算与类型转换
第15章 面向对象程序设计
概述、虚函数、抽象基类、访问控制与继承、继承中类的作用、构造函数与拷贝控制、容器与继承、文本查询程序再探
第16章 模板与泛型编程
定义模板、模板实参推断、重载与模板、可变参数模板
第17章 标准库特殊设施
tuple类型、bitset类型、正则表达式、随机数、IO库再探。
第18章 用于大型程序的工具
异常处理、命名空间、多重继承与虚继承。
第19章 特殊工具与技术
附录A 标准库
C++11新特性
简单总结主要内容:
一、基础概念与语法
这部分是 C++ 的 “基石”,涵盖程序结构、数据类型、表达式与语句等核心语法,是后续学习的基础。
1. 程序结构与基本语法
- 程序入口
所有 C++ 程序的入口都是
main()函数,其返回类型必须是int(返回 0 表示程序正常结束,非 0 表示错误状态)。 - 头文件与命名空间
-
标准库头文件不带
.h后缀(如<iostream>而非<iostream.h>),非标准库头文件可能带后缀。 std是 C++ 标准库的命名空间,使用标准库组件需显式声明:
using namespace std;(全局使用)或std::cout(局部限定),避免命名冲突。
-
- 输入输出
-
标准输入流
cin(搭配>>)、标准输出流cout(搭配<<)、标准错误流cerr(用于输出错误信息,不缓冲),定义在<iostream>中。
-
2. 数据类型与变量
C++ 数据类型分为基本类型和复合类型,核心是理解 “类型的意义(内存占用、取值范围)” 与 “变量的生命周期”。
(1)基本类型
|
类型类别 |
具体类型 |
核心说明 |
|---|---|---|
|
布尔型 |
bool |
取值仅 |
|
字符型 |
char
/ |
char
占 1 字节(区分 |
|
整数型 |
short
/ |
大小关系: |
|
浮点型 |
float
/ |
float
(4 字节,精度 6-7 位)、 |
(2)复合类型
- 引用(&)
变量的 “别名”,必须初始化且绑定后不可更改,常用于函数参数(避免拷贝)和返回值(返回对象而非拷贝)。示例:
int a = 10; int &ref = a; ref = 20; // a的值变为20。 - 指针(*)
存储变量地址的变量,可空(
nullptr,C++11 新增,替代NULL)、可指向不同对象,需注意 “空指针”“野指针”(未初始化 / 指向已释放内存)的风险。示例:int a = 10; int *p = &a; *p = 20; // a的值变为20。 - const 限定符
修饰变量为 “只读”,需初始化;修饰指针时需区分 “指针本身不可变”(
int *const p)和 “指向的内容不可变”(const int *p)。核心原则:const修饰 “其右侧最近的变量或指针”。
3. 表达式与语句
- 运算符优先级
算术运算符(
*//优先于+/-)> 关系运算符(>/<)> 逻辑运算符(&&优先于||)> 赋值运算符(=),不确定时用括号。 - 递增 / 递减运算符
++i(前置,先自增再使用)比i++(后置,先使用再自增)更高效(避免临时变量),尤其在循环或容器迭代中优先使用前置。 - 条件语句与循环
-
条件语句:
if-else(支持初始化语句,如if (int a = 10; a > 5))、switch(case 需加break,否则 “穿透”,支持string和枚举类型)。 -
循环语句:
for(C++11 支持 “范围 for”,for (auto x : container))、while、do-while(至少执行一次)。
-
二、C++11 核心特性(重点)
1. 自动类型推断(auto)
作用:让编译器根据初始化值自动推导变量类型,简化代码(尤其面对复杂类型如迭代器、容器元素类型时)。
规则:
-
-
必须初始化(否则无法推导类型)。
-
推导引用时需显式加
&(如auto &x = a,推导为引用类型)。 -
推导
const时,若变量是拷贝初始化(如auto x = const_a),const会丢失;若为引用初始化(auto &x = const_a),const会保留。
-
示例:
vector<int> vec = {1,2,3};auto it = vec.begin();// it类型为vector<int>::iterator。
2. 列表初始化({})
-
作用:统一初始化语法,支持所有类型(基本类型、数组、容器、类对象),且能避免 “窄化转换”(如
int a = {3.14}会编译报错,而int a = 3.14仅警告)。 -
场景:
-
变量初始化:
int a{10}; double b{3.14};。 -
容器初始化:
vector<int> vec{1,2,3}; map<string, int> mp{{"a",1}, {"b",2}};。 -
类对象初始化:
class A { int x; }; A a{5};(需类支持聚合初始化或有匹配构造函数)。
-
3. 范围 for 循环
-
语法:
for (declaration : sequence),遍历序列(数组、容器、初始化列表等)的每个元素,无需手动管理索引或迭代器。 -
注意:
-
若需修改元素,
declaration需为引用(auto &x);若只读,可用const auto &x(避免拷贝,高效)。 -
序列必须是可遍历的(即有
begin()和end()成员,或能被标准库begin()/end()函数处理)。
-
-
示例:
vector<int> vec{1,2,3}; for (auto &x : vec) x *= 2; // vec变为{2,4,6}。
4. 智能指针(RAII 机制)
C++11 引入智能指针,解决 “手动管理动态内存导致的内存泄漏、野指针” 问题,核心是RAII(资源获取即初始化):将资源(如动态内存)与对象生命周期绑定,对象销毁时自动释放资源。
三大智能指针定义在<memory>头文件中,对比如下:
|
智能指针类型 |
核心功能 |
使用场景 |
注意事项 |
|---|---|---|---|
unique_ptr |
独占所有权,同一时间仅一个 |
管理单个动态对象,无需共享所有权。 |
不可用 |
shared_ptr |
共享所有权,多个 |
需共享对象所有权(如容器存储指针、多线程共享对象)。 |
避免 “循环引用”(如两个 |
weak_ptr |
弱引用,指向 |
解决 |
不能直接访问对象,需通过 |
示例(unique_ptr):
unique_ptr<int> up(new int(10)); // 独占管理动态intunique_ptr<int> up2 = move(up); // 转移所有权,up变为空// 无需手动delete,up2销毁时自动释放内存
5. 右值引用与移动语义(&&)
C++11 引入 “右值引用”,解决 “拷贝大量数据导致的性能浪费” 问题,核心是区分 “左值”(可取地址、有名字的对象,如变量a)和 “右值”(不可取地址、临时存在的对象,如字面量10、函数返回的临时对象)。
- 右值引用(&&)
只能绑定右值,用于 “窃取” 右值的资源(而非拷贝),实现 “移动语义”。
- 移动构造函数 / 移动赋值运算符
-
当用右值初始化对象时,编译器优先调用移动构造函数(而非拷贝构造),直接 “接管” 右值的内存,避免拷贝。
-
若类未定义移动操作,编译器会用拷贝操作替代。
-
-
示例(移动语义):
vector<int> func() { return vector<int>{1,2,3}; }// 返回临时对象(右值)vector<int> vec1 = func();// 调用移动构造,窃取临时对象的内存,无拷贝vector<int> vec2 = move(vec1);// 强制将vec1(左值)转为右值,调用移动构造,vec1变为空
三、容器与算法(STL 核心)
C++ 标准库(STL)的 “容器 - 迭代器 - 算法” 模型是 C++ 的精髓,《C++ Primer》用大量篇幅讲解其使用与原理。
1. 容器分类与特性
STL 容器分为序列容器(按顺序存储,元素有位置关系)和关联容器(按键存储,支持快速查找),还有容器适配器(基于其他容器封装,接口更简单)。
(1)序列容器(定义在<vector>/<list>/<deque>等头文件)
|
容器类型 |
底层实现 |
核心优势 |
核心劣势 |
适用场景 |
|---|---|---|---|---|
vector |
动态数组 |
随机访问( |
中间插入 / 删除低效(O (n),需移动元素),扩容时可能拷贝数据。 |
需频繁随机访问、尾插,且插入 / 删除少的场景(如存储列表数据、缓冲区)。 |
list |
双向链表 |
任意位置插入 / 删除高效(O (1)),内存不连续,无需扩容。 |
不支持随机访问(只能迭代遍历,O (n)),每个元素需额外存储指针,内存开销大。 |
需频繁插入 / 删除,且无需随机访问的场景(如实现链表、队列)。 |
deque |
分段动态数组 |
两端插入 / 删除高效(O (1)),支持随机访问(O (1))。 |
中间插入 / 删除低效(O (n)),随机访问效率略低于 |
需两端操作、随机访问的场景(如实现栈、队列的底层容器)。 |
array |
固定大小数组 |
栈上存储,内存高效,随机访问 O (1),大小编译期确定。 |
大小不可变,不能动态扩容。 |
存储固定大小的数据(如存储 3 个坐标值 |
(2)关联容器(定义在<map>/<set>等头文件)
关联容器分为有序(基于红黑树实现,自动按键排序,查找 O (log n))和无序(基于哈希表实现,查找 O (1) 平均情况)。
|
容器类型 |
键 - 值关系 |
有序 / 无序 |
核心特性 |
|---|---|---|---|
set |
仅存储键(键唯一) |
有序 |
自动按键升序排序,键不可重复,查找是否存在某键高效。 |
multiset |
仅存储键(键可重复) |
有序 |
与 |
map |
键 - 值对(键唯一) |
有序 |
自动按键升序排序,键不可重复,通过键快速查找值( |
multimap |
键 - 值对(键可重复) |
有序 |
与 |
unordered_set |
仅存储键(键唯一) |
无序 |
哈希表实现,查找速度更快(平均 O (1)),键无序,不支持按键排序。 |
unordered_map |
键 - 值对(键唯一) |
无序 |
哈希表实现,适合高频查找场景(如缓存、字典),键无序。 |
(3)容器适配器
stack栈(LIFO,后进先出),默认基于
deque实现,支持push()(压栈)、pop()(出栈)、top()(取栈顶)。queue队列(FIFO,先进先出),默认基于
deque实现,支持push()(入队)、pop()(出队)、front()(取队首)。priority_queue优先队列(默认大顶堆),默认基于
vector实现,支持push()(插入)、pop()(删除堆顶)、top()(取堆顶)。
2. 迭代器
迭代器是 “连接容器与算法的桥梁”,行为类似指针,用于遍历容器元素,不同容器的迭代器功能不同,分为 5 类(从弱到强):
- 输入迭代器
仅支持读、++(单向),如
istream_iterator。 - 输出迭代器
仅支持写、++(单向),如
ostream_iterator。 - 前向迭代器
支持读、写、++(单向),如
forward_list的迭代器。 - 双向迭代器
支持读、写、++/--(双向),如
list、map的迭代器。 - 随机访问迭代器
支持读、写、++/--、随机访问(
+n/-n/[]),如vector、deque、array的迭代器。
核心操作:
*it访问迭代器指向的元素。
it->访问迭代器指向对象的成员(如
map的迭代器指向pair,it->first获取键)。++it迭代器向后移动(优先使用前置)。
it1 == it2判断两个迭代器是否指向同一位置。
注意:容器的erase()操作会使 “指向被删除元素的迭代器失效”,需通过erase()的返回值(指向被删除元素的下一个元素)更新迭代器,避免野指针。
3. 算法(STL 算法库)
STL 算法定义在<algorithm>头文件中,分为非修改算法(不改变容器元素,如查找、计数)和修改算法(改变容器元素,如排序、拷贝、替换),均通过迭代器操作容器,与容器类型无关。
常用算法示例:
- 查找
find(beg, end, val)(在[beg,end)中查找val,返回迭代器,未找到返回end)、count(beg, end, val)(计数val出现次数)。 - 排序
sort(beg, end)(默认升序排序,需随机访问迭代器,如vector)、stable_sort(beg, end)(稳定排序,保持相等元素的相对位置)。 - 拷贝
copy(beg_in, end_in, beg_out)(将[beg_in,end_in)的元素拷贝到beg_out开始的位置,需确保目标空间足够)。 - 替换
replace(beg, end, old_val, new_val)(将[beg,end)中所有old_val替换为new_val)。 - 累加
accumulate(beg, end, init)(从init开始,累加[beg,end)的元素,定义在<numeric>头文件)。
四、高级主题
1. 函数与函数模板
- 函数参数
支持默认参数(默认参数需从右往左定义,如
void func(int a, int b=10))、可变参数(C++11 的initializer_list<T>,用于接收任意数量的同类型参数,如void func(initializer_list<int> args))。 - 函数重载
同一作用域内,函数名相同但参数列表(参数个数、类型、顺序)不同,编译器根据实参匹配最佳函数;返回值类型不同不能构成重载。
- 函数模板
定义通用函数,编译器根据实参类型自动生成具体版本(模板实例化),语法:
template <typename T> T add(T a, T b) { return a + b; },支持模板特化(为特定类型定制实现)。
2. 类与对象
- 类的基本成员
成员变量(可加
public/private/protected访问控制,默认private)、成员函数(普通成员函数、构造函数、析构函数、静态成员函数)。 - 构造函数
用于初始化对象,无返回值,与类名相同;支持重载、默认构造函数(无参数或参数全有默认值,若用户定义了其他构造函数,编译器不再生成默认构造)、拷贝构造函数(用同类型对象初始化新对象,默认浅拷贝,若有动态内存需自定义深拷贝)。
- 析构函数
用于释放对象资源(如动态内存、文件句柄),无参数、无返回值,与类名相同且加
~,仅一个;若类有动态内存,必须自定义析构函数,避免内存泄漏。 - 静态成员
用
static修饰,属于类而非对象,所有对象共享;静态成员变量需在类外初始化,静态成员函数无this指针,不能访问非静态成员。
3. 继承与多态
- 继承
子类(派生类)继承父类(基类)的成员,语法:
class Derived : public Base { ... };访问控制:public继承(基类public成员为子类public,protected为protected)、private继承(基类成员均为子类private)、protected继承(基类public/protected成员为子类protected)。 - 多态
通过 “虚函数” 实现,基类声明虚函数(
virtual void func()),子类重写(override,C++11 关键字,显式声明重写,避免错误),通过基类指针 / 引用调用时,会根据对象实际类型调用对应版本的函数。 - 抽象类
包含纯虚函数(
virtual void func() = 0)的类,不能实例化,只能作为基类,子类必须重写纯虚函数才能实例化。
4. 异常处理
-
语法:
try(包裹可能抛出异常的代码)、throw(抛出异常,可抛任意类型)、catch(捕获异常,按类型匹配,...捕获所有类型异常)。 -
原则:异常用于处理 “异常情况”(如文件打开失败、内存分配失败),而非正常逻辑判断;抛出的异常应能被捕获,否则程序终止;C++ 标准库定义了标准异常类(如
std::runtime_error、std::out_of_range),可自定义异常类继承自标准异常。
更多推荐
所有评论(0)