C++
…
C++ 官网
C++ 编译
编译环境判断
1 | // C++0X |
调用C语言代码
1 | extern "C" { /* C代码 */ } |
类和对象
继承
重载
多态
数据抽象和封装
接口
文件和流
异常
动态内存
模板
信号
多线程
Web
C++ 历史
从开始有:C++98,C++03,C++TR1,C++14,C++ 扩展,C++17,C++20。
C++98是C++标准第一版,C++03是第二版,与C++98几乎一样,没做什么修改。
C++11
新增nullptr
来表示空指针。
auto 类型:
在C++11中,auto
被赋予了新的含义,即自动推导出变量类型。例如:
1 | auto name = "John"; |
这里,auto
仅仅是一个占位符,在编译器期间它会被真正的类型所替代。或者说,C++ 中的变量必须是有明确类型的,只是这个类型是由编译器自己推导出来的。
auto
常用于定义迭代器,泛型编程等。
1 | // 迭代器 |
但auto
的使用也是有限制的:
- 不能用作函数的形参;
- 不能作用域类的非静态成员变量;
- 不能定义数组;
1 | auto str[] = url; //arr 为数组,所以不能使用 auto |
- 不可作用于模板参数;
1 | template <typename T> |
decltype:
decltype
也是在编译使其进行自动类型推导的关键字,意为声明类型(declare type),用于某些auto
无法使用的情况下。基本形式为:
1 | decltype(exp) varname; |
exp
是一个普通的表达式,其结果必须是有类型的,不可是void
。该关键字可以通过exp
的类型定义varname
的类型。具体推导规则如下:
exp
没有被()
包裹,那么则返回exp
的类型;exp
被()
包裹,或是一个左值,那么则返回exp
的引用类型;
二者的区别在于:
decltype
会保留CV限定符(const
/volatile
),auto
会在表达式的类型是指针或引用时才保留CV限定符;decltype
会保留引用类型,auto
会抛弃引用类型;
返回值类型后置:
这一语法可以将decltype
与auto
结合起来完成返回值类型的推导。
1 | // 例如 |
连续的右尖括号 >>
C++98/03中不允许连续的>>
,在C++11中可以。
begin和end
不必使用x.begin()
,而是可以直接调用begin
函数:
1 | sort(begin(v), end(v)); |
using 关键字
using覆盖了typedef的全部功能,并增添了一些新的特性,改善了对模板的支持。
1 | // 重定义unsigned int |
模板默认参数
在C++98/03中,类模板可以有默认的模板参数,但是函数却没有。在C++11中,函数也可以用默认模板参数了。
函数在使用默认模板参数时,可以像普通函数一样调用。但是类必须加上<>
。
若要填充模板参数,则要遵循从右向左的方式填充。
模板参数也支持了变长。
元组:
1 | auto p = make_pair(1, "C++ 11"); |
列表初始化
初始化的适用性大大增加了:
1 | // 用于类 |
新的for循环
新的基于范围的for循环:
1 | // 数组 |
lambda
1 | auto f = [](int a) -> int { return a + 1; }; |
非受限联合体 Union
过去C++98不允许联合体成员是非POD类型,但是只会取消了这种限制。
POD数据类型是:
- 没有自定义的构造函数,析构函数,拷贝构造,移动构造。
- 没有虚函数和虚基类。
- 非静态成员必须是public。
- 类的第一个非静态成员类型与基类不同。
- 类或结构体继承时,派生类有非静态成员,且仅包含静态成员的基类;基类有非静态成员,而派生类没有非静态成员。
- POD 类型不能包含非 POD 类型的数据。
- 所有兼容C语言的数据类型都是 POD 类型。
也就是说,能用 C 的 memcpy() 等函数进行操作的类、结构体就是 POD 类型的数据。
智能指针<memory>
:
这里包含了三种智能指针: shared_ptr unique_ptr weak_ptr。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。
1 | // 多个指针指向相同的对象 |
右值引用
左值右值:左值指的是可以取地址的,有名字的,非临时的就是左值,右值指的则是不能取地址的,没有名字的,临时的就是右值。可见立即数,函数返回的值等都是右值;而非匿名对象(包括变量),函数返回的引用,const对象等都是左值。
左值引用:左值引用要求右边的值必须能够取地址,如果无法取地址,可以用常引用。
右值引用:右值引用用来绑定到右值,绑定到右值以后本来会被销毁的右值的生存期会延长至与绑定到它的右值引用的生存期。右值引用可以进行读写操作,而常引用只能进行读操作。
1 | int &&var = 10; |
Move/&&
通过move构造和move赋值可以避免内存重新分配。
1 | // move constructor |
Bind: 可以把一个参数较多的函数给封装成参数较少的函数,重排源函数的参数顺序等
1 | auto newFun = bind(oldFun,arg_list); |
C++14
C++ 14 是 C++ 11 的增量更新,主要是支持普通函数的返回类型推演,泛型 lambda,扩展的 lambda 捕获,对 constexpr 函数限制的修订,constexpr变量模板化等等。
C++17
C++20
技术分层
基础部分:
- C基础:数据结构,结构体,函数,递归等
- 数据结构:链表,栈,队列,树,二叉树,B树,图
- 系统编程:基本操作,Shell,进程通信
进阶部分:接口的设计和封装,模块的划分。
- 日志
- 配置文件
- Linux/Win下IPC库
- Socket库
- 数据库统一访问
高级部分:
- Win 项目案例
- Linux 项目案例
- Android/IOS 案例
算法
algorithm内涉及到元素本身的操作无非是比大小。
1 | // C++ :: 全局函数 查找 |