STL源码剖析_阅读笔记

ifdef和#if defined()的区别 | placement new | 函数指针 | void (set_malloc_handler(void (__f)()))() |

#ifdef和#if defined()的区别

1
2
3
4
5
6
7
8
9
10
11
后者可以组成复杂的预编译条件,比如
\#if defined (AAA) && defined (BBB)
xxxxxxxxx
\#endif
\#if defined (AAA) || VERSION > 12
xxxxxxxxx
\#endif
#ifdef 就不能用上面的用法

也就是说,当你要判断单个宏是否定义时
\#ifdef 和 #if defined 效果是一样的,但是当你要判断复杂的条件时,只能用 #if

placement new

STL源码剖析中,空间配置器一章有这样一段代码:

1
2
3
4
5
6
\#include <new.h>

template <class T1, class T2>
inline void _construct(T1* p, const T2& value) {
new(p) T1(value); // placement new. invoke ctor of T1
}

这个操作叫做placement new,就是在指针p所指向的内存空间创建一个T1类型的对象,但是对象的内容是从T2类型的对象转换过来的(调用了T1的构造函数,T1::T1(value))。
就是在已有空间的基础上重新调整分配的空间,类似于realloc函数。这个操作就是把已有的空间当成一个缓冲区来使用,这样子就减少了分配空间所耗费的时间,因为直接用new操作符分配内存的话,在堆中查找足够大的剩余空间速度是比较慢的。
placement new的好处:
  在已分配好的内存上进行对象的构建,构建速度快。
  可以反复利用同一块已分配好的内存,有效的避免内存碎片问题。
  建立对象数组时,能够调用带参数的构造函数。

将一个数上调到8的倍数的技巧

STL源码剖析中,STL的第二级配置器会将任何小额区块上调为8的倍数。

1
2
3
int round_up(int bytes){
return ((bytes+7) & ~7);
}

obj volatile my_free_list

《STL源码剖析》p64。

1
2
3
volatile关键字是为了防止cpu优化的,可以先去掉。
先看obj *my_free_list; //这里的my_free_list是一个指针,指向obj类型的变量。
obj* *my_free_list; //这里的my_free_list是一个指针,指向另一个指针(这个指针指向一个obj),也就是说my_free_list是指向指针的指针。

set_malloc_handler

之前只见过函数指针

1
2
3
4
5
6
7
void(*fun)(),意思是定义了一个函数指针(这是一个变量),指向一个返回值和参数都为空的函数
可以让它指向一个函数,然后调用这个指针,可以起到调用函数的效果
void test(){
...
}
fun=test;
(*fun)(); //可以这样用,相当于调用test()

在STL空间配置器部分,有这样的用法:

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
static void (* __set_malloc_handler(void (*__f)()))()
这其实是定义了一个函数__set_malloc_handler,而不是函数指针。
void(* __f)()是__set_malloc_handler函数的参数(这个参数是函数指针)
函数的返回值是void(*)()类型的,可以这样来使用:

void pri(){
cout<<"pri"<<endl;
}

void (*fun(void (*f)()))(){
f();
return f;
}

int main()
{
void (*tmp)();
tmp=fun(pri); //fun接收一个函数指针类型的参数,然后返回一个函数指针类型的值。
tmp();
}

再看这个:
void (* fun() )(){
...
}
它的意思是定义了一个函数fun,fun()的参数为空,返回值是void(*)()类型的。
当然可以这样写,更好理解一些:
typedef void(*Type)(); //这个是定义了一种类型
Type fun(){
...
}
所以我们前面的 static void (* __set_malloc_handler(void (*__f)()))(),可以改成这样:
typedef void(*Type)();
static Type __set_malloc_handler(Type)

linux和windows中都有这样的用法,可以参考这个链接:https://blog.csdn.net/woyaowenzi/article/details/6086064
可能难理解的地方就在于,用void(*)()这样的方式来修饰函数的返回值吧。
不得不说Cpp的语法真是麻烦…

参考

欢迎与我分享你的看法。
转载请注明出处:http://taowusheng.cn/