概述
文章目录
- 简介
- 六大组件
- 文件分布
- 测试
- 对do...while(0)的疑惑
- 使用
简介
STL一直在使用,有时候就想了解了解其中的实现原理,顺便复习复习数据结构和算法。
因为我水平有限,所以先找了一个简化版的MyTinySTL源码来看,配上STL源码剖析这本书,大概是能看懂一些了,这边简单记录一下。
并且还搬运了一些STL源码分析上面的内容,实在是比较懒,想看完整的可以看原本的博客。
六大组件
- 分配器:用来管理内存。
- 迭代器:将容器和算法粘合在一起,用来遍历STL容器中的部分或全部元素。
- 容器:封装了大量常用的数据结构。
- 算法:定义了一些常用算法。
- 仿函数:具有函数特质的对象。
- 适配器:主要用来修改接口。
文件分布
组件 | 文件 |
---|---|
分配器 | construct.h、allocator.h |
迭代器 | iterator.h、type_traits.h |
容器 | astring.h、basic_string.h、vector.h、list.h、deque.h、stack.h、queue.h、rb_tree.h、set.h、map.h、hashtable.h、unordered_set.h、unordered_map.h |
算法 | uninitialized.h、algorithm.h、algobase.h、algo.h、set_algo.h、heap_algo.h、numeric.h |
仿函数 | functional.h |
配接器 | 分布在很多角落 |
测试
MyTinySTL自己编写了函数用来测试都在test.h中,注释很全。
首先定义了输出的颜色,green代表成功 red代表失败。
#define green redbud::io::state::manual << redbud::io::hfg::green
#define red redbud::io::state::manual << redbud::io::hfg::red
然后有两个类分别是单个测试和运行多个测试。
// 封装单个测试案例
class TestCase
{
public:
// 构造函数,接受一个字符串代表案例名称
TestCase(const char* case_name) : testcase_name(case_name) {}
// 一个纯虚函数,用于测试案例
virtual void Run() = 0;
public:
const char* testcase_name; // 测试案例的名称
int nTestResult; // 测试案例的执行结果
double nFailed; // 测试失败的案例数
double nPassed; // 测试通过的案例数
};
// 单元测试,把所有测试案例加入到 vector 中,依次执行测试案例
class UnitTest
{
public:
// 获取一个案例
static UnitTest* GetInstance();
// 将案例依次加入 vector
TestCase* RegisterTestCase(TestCase* testcase);
void Run();
public:
TestCase* CurrentTestCase; // 当前执行的测试案例
double nPassed; // 通过案例数
double nFailed; // 失败案例数
protected:
std::vector<TestCase*> testcases_; // 保存案例集合
};
实现都很简单,后面还有一系列的宏用来进行断言操作。
对do…while(0)的疑惑
刚开始看的时候我还是很好奇为什么宏定义中要用do...while(0)
,如:
#define EXPECT_TRUE(Condition) do {
if (Condition) {
UnitTest::GetInstance()->CurrentTestCase->nPassed++;
std::cout << green << " EXPECT_TRUE succeeded!n";
}
else {
UnitTest::GetInstance()->CurrentTestCase->nTestResult = 0;
UnitTest::GetInstance()->CurrentTestCase->nFailed++;
std::cout << red << " EXPECT_TRUE failed!n";
}} while(0)
既然循环里面只执行了一次,我要这个看似多余的do...while(0)
有什么意义呢?
我们举个例子
有一个宏:
#define _DELETE(p) do{ delete p; p = NULL} while(0)
去掉do…while(0):
#define _DELETE(p) delete p; p = NULL;
调用
if(NULL != p) _DELETE(p)
else ...do sth...
可能有人已经发现了去掉do…while(0)我们的代码可能会变成:
if(NULL != p) delete p; p = NULL;
else ...do sth...
if分支后有两个语句,else分支没有对应的if,编译失败。
假设没有else, _DELETE中的第二个语句无论if测试是否通过,会永远执行。
有人说我写的if绝对加{}
,但是我们不能保证其他人对吧。
还有人可能会想我不能用{}
吗一定要用do...while(0)
吗?
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,在每个语句后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) _DELETE(p);
else ...do sth...
else就没法编译了。
使用
TEST(first)
{
EXPECT_TRUE(true);
}
int main()
{
RUN_ALL_TESTS();
return 0;
}
运行结果:
最后
以上就是激动小海豚为你收集整理的MyTinySTL阅读笔记---概述简介六大组件文件分布测试的全部内容,希望文章能够帮你解决MyTinySTL阅读笔记---概述简介六大组件文件分布测试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复