基础语法
编译
- 预处理 Preprocessing cpp test.cpp -> test.i
- 编译 Compilation g++ -g -S test.i
- 汇编 assembly as -o test.o test.s gcc -g -c test.c;
- 链接 linker ld -o …
表达式
左值右值
lvalue, rvalue
In C: 左值可以放在赋值语句左边,右值则不行。
左值利用的主要是对象的身份,右值则利用的是对象的值
- decltype 作用左值时自动变成引用
- 取地址符作用于一个左值,返回一个右值(指针)
- 赋值运算符左侧作为左值运算对象
类型转换
一般来说是占用空间小的向占用空间大的方向转换,如果相同则无符号转换。
- 数组转换为指针:赋值时
- 指针转换
- 转换为bool
- non-const 指针或引用 向const 指针或引用转换
- 类的类型转换 如
while (cin >> str)
IO库中定义了istream转换规则。
显示转换:
- 强制类型转换
- 命名的强制类型转换
- static_cast
double db = static_cast<double>(j) /i;
大转小也可以(精度损失) - dynamic_cast 支持运行时类型识别
- const_cast 改变运算对象的底层const,去掉const,只能改变const属性,无法改动类型
- static_cast
异常
throw
,结束程序执行,回到函数调用处,抛出一个异常,并做资源清理try-catch
1 | class MyException : public exception { |
STL
IO
头文件
- iostream
- fstream
- sstream
状态查看
- s.bad()
- s.good()
- s.fail() 数据错误
- s.bad() IO流错误
- s.clear() 状态位复位
- s.eof() 文件结束符
流
为什么要有Stream ?
Stream 是输入输出的抽象,提供了String类型和别的类型数据的相互转换
Stream分类:
- 输入流 InputStream
- 输出流 OutputStream
输出流
只能用 << 符号接受数据,将数据转换为String并发送给Stream
举例:
- std::cout
- std::ofstream :file stream是一种type
- ostringstring :把String当成Stream
fstream 文件的例子
1 | //You should include fstream |
- 打开文件
void open(const char *filename), ios::openmode mode);
- ios::app 追加到文件末尾
- ios::ate 定位到文件末尾
- ios::in 用于读取
- ios::out 写入文件
- ios::trunc 截断模式,覆盖掉原有
- e.g.
ofstm.open("file.dat", ios::out|ios::trunc);
- 关闭 void close();
ostringstream 的例子(stringstream可以读入读出):字符串的例子
1 |
|
1 | Ito En Green Tea |
输入流
- std::cin
- ifstream
fstream 的例子
1 | //You should include fstream |
mystream.fail()
可以检测stream是否fail,例如
- 读文件读到结束
- 文件不存在
- 读入的类型错误
注意的问题
cin 一直读到空格,换行符等,如果输入单词可能有问题
但是要用getline要注意下面的问题
1 | cin >> val; |
1 | cin >> val; |
第二次读入的就是第一次的\n,因为cin 并不会处理后面的\n,只将前面的 \n 空格略去,等于说此时getline
在streambuffer里读入的是第一次结尾的\n。
string
- size(), 返回string::size_type
- empty()
[]
以string::size_type为索引,注意类型是unsigned 的- 字符串相关操作:
- str1 + str2
- str1 + “字面量”
- os << str, is >> s
- getline(cin, str),读取一行,丢弃换行符
- == 按字符序比大小,如果前面相同比长度,长者大
- cctype 头文件
- isupper(), toupper() 大写
- islower(), tolower() 小写
- isdigit(), isalpha() 数字和字幕
- ispunct() 标点
- isspace() 空白
顺序容器
顺序容器的元素排列顺序与其值无关,而仅仅由元素添加到容器里的次序决定。
vector
功能:
- 创建
vector<int> a(v2)
;vector<int> a = v2
;vector<int> a{0, 1, 2, 3, 4}
;vector<int> a = {0, 1, 2, 3, 4}
;vector<int> a(n)
: 初始化为0vector<int> a(n, val)
: n个以val为值的vector元素
- 增加
- push_back(val):在最后增加
- insert(index, val):在index处(或理解为index前面)增加
- 删除
- erase(v.begin()+i):按地址删除
- pop_back();
- clear():清除所有
- 修改
- v[i] = val:没有边界检查
- v.at(i) = val
- 查找
- v.at(i)
- v[i] :没有边界检查
- v.front();
- v.back();
- 其他
- v.empty();
- v.reserve(size): 预留size个地方
deque
双端队列,跟vector类似,用的比较少,好处在于大量插入删除操作时速度快
有和vector一样的函数,还有front操作:
- push_front(val)
- pop_front()
list
插入删除开销少,但是不能根据index进行快速定位
有front操作:
- push_front(val)
- pop_front()
使用技巧
- 可以先reserve一定大小
1 | vec.reserve(1000000); |
关联容器
set
multiset
map
multimap
基于hash table的容器
unordered_map
unordered_set
iterator
迭代器
- begin(), end() 返回首尾迭代器,是否为const由元素决定
- cbegin(),cend()返回const_iterator
- 算术运算+-
泛型算法
参考C++Primer第10章
智能指针
<memory>
- unique_ptr : move 语意, 资源只有一个指向它
- shared_ptr : copy 语意, 资源可以有多个指向它,要知道最后一个用的,没有人指向我,那就delete
- weak_ptr
1 | unique_ptr<classA> r1 { std::make_unique<classA>()}; |
常用:
1 | unique_ptr<X> make_X(int i) { |
RAII
RAII: Resource acquisition Is Initialization
资源获取即初始化
lambda 表达式
- 匿名函数
- capture list 外部变量访问方式说明符
=
只读&
可修改- 空的,不用到外面的变量
[=, &x, &y]
,x,y 可改,其余变量不能修改[&, x, y]
除了x,y以外的外部变量都可以修改
->
可以省略,让编译器自己推导
1 | [capture list] (parameter list) -> int { |
- C++14 generic lambda
类型转换
显式
- C style: (type) expression
const_cast<type>
(expr): 修改类型的const属性dynamic_cast<type> (expr)
: runtime 执行转换,若失败,expr被认定为nullptr,若引用失败catch std::bad_caststatic_cast<type>
: 非动态转换,没有运行时类检查来保证转换的安全性,例如int到size_treinterpret_cast<type> (expr)
: 最好不用
隐式类型转换
- 注意类的隐式类型转换
- 例如有函数combine(const Sale_data &sd),且有构造函数可以接受string, 则combine(string(“str”))则会默认生成一个Sale_data类
- 拷贝形式: Sales_data item = string(“str”);
- 可以使用
explicit
关键字避免不期望的隐式类型转换
命名空间
- 定义一个范围
- 类本身就是一个特殊的命名空间
1 | namespace My_code { |
- 不要在头文件里使用命名空间(using namespace …)
OOP
C struct:
- 没有封装
- 没有操作
类Class
- 数据抽象
- 封装
- private
- public
- protected (子类)
- 动态绑定(运行时绑定)
函数
1 | class X { |
friend 函数
定义在类外部
有权访问累的所有private 成员和protected 成员
friend 函数并不是成员函数
相同Class的各个objects互为friends
const
- 常量成员函数
- 常量对象 -> 只能调用 const 函数
const & constexpr
- 修饰对象
- const主要表示这是个常量,不会变动
- constexpr是修饰一个常量表达式
- 修饰函数
- const只能用于非静态成员函数,保证函数不修改任何非静态数据
- constexpr适用于常量表达式,通常是简单函数,只允许return语句,参数和返回值必须是字面量。
virtual
virtual 关键字
在继承时通过晚绑定和vtable来实现多态,这样就可以用基类指针来操作各种派生类。
纯虚函数
- vitual double function() = 0;
声明一个function为接口,接口类不能被实例化,但是可以有成员变量,该类是纯虚类。
类的不可改性
- const 成员函数
- const 成员变量
- class 为final: class A final {} 不能再被继承了
其他
- 递归
- 好处:
- 分而治之
- 简洁性好
- 好处:
- 迭代
- 好处
- 效率高:编译器在同一个stack里面容易优化代码,cross-stack 优化不容易做
- 好处