C++ 学习计划
May 21, 2018
- 0. 学习内容
- 1. 现代C++的思想
- 1.1 基于堆栈的范围,而非堆或静态全局范围。
- 1.2 优先使用auto,而非显式类型名称。
- 1.3 智能指针,而非原始指针。
- 1.4 std::string 和 std::wstring 类型,而非原始 char[] 数组。
- 1.5 标准模板库 (STL) 容器(例如 vector、list 和 map),而非原始数组或自定义容器。
- 1.6 STL 算法,而非手动编码的算法。
- 1.7 异常,可报告和处理错误条件。
- 1.8 使用 STL std::atomic<>(请参见
),而非其他线程间通信机制的无锁线程间通信。 - 1.9 内联 lambda 函数,而非单独实现的小函数。
- 1.10 基于范围的 for 循环,编写以 for ( for-range-declaration : expression ) 形式使用数组、STL 容器和 Windows 运行时集合的更可靠循环。
- 2. 使用Eclipse Memory Analyzer分析内存
- 3. 找到泄露原因
- 4. LeakCanary不是万能的
0. 学习内容
目前准备在未来两个月中深入学习C++的一些重要的课题,在此制定一个阅读和学习计划。
C++博大精深、海纳百川,特别是在C++11之后的几代标准,使C++如何避免写出难以维护的代码,需要在长期的实践中不断提高自己的水平,丰富自己的知识。
这次的学习计划主要有如下内容:
- 现代C++的思想
- STL的使用
- 序列式容器库
- 关联式容器库
- 算法库
- allocator
- C++11 https://coolshell.cn/articles/5265.html
- lambda表达式
- 自动类型auto
- nullptr
- delete和default函数
- 右值引用和move
- 显式虚函数重载 override
- 类型安全的枚举
- C++ 11 STL 标准库 :线程、智能指针
- 模板
1. 现代C++的思想
1.1 基于堆栈的范围,而非堆或静态全局范围。
现代C++提倡
1.2 优先使用auto,而非显式类型名称。
使用自动类型推导主要有以下好处:
- 避免冗长的类型
- 防止未初始化的变量 int x1; // 有潜在的未初始化风险 auto x2; // 编译错误!必须有初始化物 auto x3 = 0; // 没问题,x的值初始化了
- 防止意外的类型转换 比如下面的这段代码:
std::unordered_map<std::string, int> m;
...
for (const std::pair<std::string, int>& p : m) {
...
}
哈希表中的std::pair其实应该是std::pair<const std::string, int>
,上面的写法编译器会对m中的每个对象做一次复制操作,生成一个p想要绑定的临时对象,在循环结束时这个临时对象将被析构一次,导致这个循环在性能上并不是最佳的。而这个问题可以用for(const auto &p :m)
很轻易地来解决。
但是auto并不是完美的,有一部分情况下无法使用auto或者不适合使用auto
1.3 智能指针,而非原始指针。
1.4 std::string 和 std::wstring 类型,而非原始 char[] 数组。
1.5 标准模板库 (STL) 容器(例如 vector、list 和 map),而非原始数组或自定义容器。
1.6 STL 算法,而非手动编码的算法。
1.7 异常,可报告和处理错误条件。
1.8 使用 STL std::atomic<>(请参见 ),而非其他线程间通信机制的无锁线程间通信。
1.9 内联 lambda 函数,而非单独实现的小函数。
1.10 基于范围的 for 循环,编写以 for ( for-range-declaration : expression ) 形式使用数组、STL 容器和 Windows 运行时集合的更可靠循环。
传统的C++代码片段示例
// circle and shape are user-defined types
circle* p = new circle( 42 );
vector<shape*> v = load_shapes();
for( vector<circle*>::iterator i = v.begin(); i != v.end(); ++i ) {
if( *i && **i == *p )
cout << **i << “ is a match\n”;
}
for( vector<circle*>::iterator i = v.begin();
i != v.end(); ++i ) {
delete *i; // not exception safe
}
delete p;
#include <memory>
#include <vector>
// ...
// circle and shape are user-defined types
auto p = make_shared<circle>( 42 );
vector<shared_ptr<shape>> v = load_shapes();
for_each( begin(v), end(v), [&]( const shared_ptr<shape>& s ) {
if( s && *s == *p )
cout << *s << " is a match\n";
} );
2. 使用Eclipse Memory Analyzer分析内存
首先下载它:www.eclipse.org/mat/downloads.php 然后安装它:这里不啰嗦了
以下用mat代替Eclipse Memory Analyzer