Boost源码分析笔记

最近在读Boost的代码,将一些Boost库中好用的模块用法以及实现分析写一下咯,不定期更新。

注意:在使用Boost时不要再偷懒直接使用using namespace std;了,因为Boost中有很多和标准库中重名的情况,而namespace的引入也正是为了解决这个问题,合理正确地使用命名空间,是一个合格的cpper应该做的事。

Timer

目前版本的Boost(1.62)中含有两个版本的timer,一个是timer(v1),是使用C/C++库函数实现的低精度(依赖于操作系统或编译器)版本,timer不需要链接库,只需要包含<boost/timer.hpp>;二是cpu_timer(v2),是基于chrono库使用操作系统的API,计时的精度更高。

timer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <boost/timer.hpp>

using namespace std;
using namespace boost;

int main(int argc,char* argv[])
{
timer t;
cout<<t.elapsed_max()<<endl;
cout<<t.elapsed_min()<<endl;
cout<<t.elapsed()<<endl;
return 0;
}

Boost中的timer是通过调用C/C++的库函数clock()来实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class timer
{
public:
timer() { _start_time = std::clock(); } // postcondition: elapsed()==0
// timer( const timer& src ); // post: elapsed()==src.elapsed()
// ~timer(){}
// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed()
void restart() { _start_time = std::clock(); } // post: elapsed()==0
double elapsed() const // return elapsed time in seconds
{ return double(std::clock() - _start_time) / CLOCKS_PER_SEC; }

double elapsed_max() const // return estimated maximum value for elapsed()
// Portability warning: elapsed_max() may return too high a value on systems
// where std::clock_t overflows or resets at surprising values.
{
return (double((std::numeric_limits<std::clock_t>::max)())
- double(_start_time)) / double(CLOCKS_PER_SEC);
}

double elapsed_min() const // return minimum value for elapsed()
{ return double(1)/double(CLOCKS_PER_SEC); }

private:
std::clock_t _start_time;
}; // timer

std::clock()是在C++中的ctime.h中定义的:

1
std::clock_t clock(void);

其中std::clock_t也定义在ctime.h中。

Defined in header
typedef /* unspecified */ clock_t;
Arithmetic type capable of representing the process running time of implementation-defined range and precision.

其实上面调用timer的代码就等同于:

1
2
3
4
5
6
7
8
9
10
11
#include <iosteram>
#include <ctime.h>
using namespace std;

int main(void){
clock_t start=clock();
// elapsed_max与elapsed_min的算法同上
// elapsed
clock_t end=clock()-start/CLOCKS_PER_SEC;
return 0;
}

注意:每秒的clock数由宏CLOCKS_PER_SEC定义,CLOCKS_PER_SEC的值在各个操作系统下不一。在win32下是1‘000(计时精度则为1s/1’000=1ms(毫秒)),在Linux下是1’000’000(计时精度为1s/1’000’000=1μs(微秒))。

progress_timer

progress_timer继承自timer类,因此具有timer类的所有成员函数(接口与timer相同),我们可以progress_timer对象进行可对timer对象的任何操作。

progress_timer的构造函数由timer的构造函数+progress_timer中定义的构造函数构成。progress_timer构造时需传递一个IO流对象,以便析构时将时间输出至该流。默认是std::cout,也可以使用其他标准输出流(ofsttream/ostringstream)替换,或者时所用cout.rdbuf()重定向cout的输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public:
explicit progress_timer( std::ostream & os = std::cout )
// os is hint; implementation may ignore, particularly in embedded systems
: timer(), noncopyable(), m_os(os) {}
~progress_timer()
{
// A) Throwing an exception from a destructor is a Bad Thing.
// B) The progress_timer destructor does output which may throw.
// C) A progress_timer is usually not critical to the application.
// Therefore, wrap the I/O in a try block, catch and ignore all exceptions.
try
{
// use istream instead of ios_base to workaround GNU problem (Greg Chicares)
std::istream::fmtflags old_flags = m_os.setf( std::istream::fixed,
std::istream::floatfield );
std::streamsize old_prec = m_os.precision( 2 );
m_os << elapsed() << " s\n" // "s" is System International d'Unites std
<< std::endl;
m_os.flags( old_flags );
m_os.precision( old_prec );
}
catch (...) {} // eat any exceptions
} // ~progress_timer
private:
std::ostream & m_os;

可以看到,当我们构造一个progress_timer时会自动开始计时(timer::timer()),并且在progress_timer析构时会输出从对象构造开始至析构期间的时间。

progress_display

progress_display可以在控制台显示程序的执行进度,我觉得这个类没什么卵用就不写了…

date_time

Boost有date_time库用来处理时间,date_time需要编译才能使用,需要在编译时链接boost_date_time库。
date_time包含两部分,一是处理日期的gregorian和处理时间的posix_time

更多关于boost中date_time的接口用法可以看这里:Chapter 10. Boost.Date_Time

date_time基本涵盖了我们对于日期之间计算的需求,不过date_time库的日期基于格里高利历,只能支持从1400-01-01到9999-12.31之间的日期。

这个废话也不多说,直接看一些简单常用的用法…更多的用法可以看Boost的文档或者《Boost程序库完全开发之南》。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>

int main(int argc,char* argv[])
{
boost::gregorian::date testDate(2016,10,19);

// 判断是否是一个有效时间
if(!testDate.is_not_a_date())
{
std::cout<<"yes"<<std::endl;
}else{
std::cout<<"error"<<std::endl;
}
// 访问日期
std::cout<<testDate.year()<<"-"<<testDate.month()<<"-"<<testDate.day()<<std::endl;
std::cout<<testDate<<std::endl;
// 计算两个日期间隔
boost::gregorian::date init(1994,11,11);
boost::gregorian::date now(2016,10,19);
std::cout<<now-init<<std::endl;

// 日期运算
// boost::gregorian::date test(2016,10,19);
// years()/months()/days() define in boost::gregorian namespace
// tommrow
boost::gregorian::date tommrrow=now+boost::gregorian::days(1);
std::cout<<tommrrow<<std::endl;
// next month
boost::gregorian::date nextMonth=now+boost::gregorian::months(1);
std::cout<<nextMonth<<std::endl;
// next year
boost::gregorian::date nextYear=now+boost::gregorian::years(1);
std::cout<<nextYear<<std::endl;

return 0;
}

date_time中date类的部分代码:

具体的可以看boostcode/date_time/date.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
template<class T, class calendar, class duration_type_>
class date : private
boost::less_than_comparable<T
, boost::equality_comparable<T
> >
{
private:
typedef T date_type;
typedef calendar calendar_type;
typedef typename calendar::year_type year_type;
typedef typename calendar::month_type month_type;
typedef typename calendar::day_type day_type;
typedef typename calendar::ymd_type ymd_type;
public:
// 构造函数
date(year_type y, month_type m, day_type d)
: days_(calendar::day_number(ymd_type(y, m, d)))
{}
date(const ymd_type& ymd)
: days_(calendar::day_number(ymd))
{}

// 成员函数
year_type year() const
{
ymd_type ymd = calendar::from_day_number(days_);
return ymd.year;
}
month_type month() const
{
ymd_type ymd = calendar::from_day_number(days_);
return ymd.month;
}
day_type day() const
{
ymd_type ymd = calendar::from_day_number(days_);
return ymd.day;
}
bool is_not_a_date() const
{
return traits_type::is_not_a_number(days_);
}

//重载操作符
date_type operator-=(const duration_type& dd)
{
*this = *this - dd;
return date_type(days_);
}
date_rep_type day_count() const
{
return days_;
}
//allow internal access from operators
date_type operator+(const duration_type& dd) const
{
if(dd.is_special())
{
return date_type(date_rep_type(days_) + dd.get_rep());
}
return date_type(date_rep_type(days_) + static_cast<date_int_type>(dd.days()));
}
date_type operator+=(const duration_type& dd)
{
*this = *this + dd;
return date_type(days_);
}

};

Smart Pointer

全文完,若有不足之处请评论指正。

微信扫描二维码,关注我的公众号。

本文标题:Boost源码分析笔记
文章作者:查利鹏
发布时间:2016年10月19日 21时39分
本文字数:本文一共有1.6k字
原始链接:https://imzlp.com/posts/18194/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!