【STL源码剖析】令人困惑的语法

困惑的语法

obj * volatile * my_free_list的含义

这个声明原来的形式是:obj** my_free_list,这样的话*my_free_list(空闲的内存块指针数组中的一个元素)可能被优化到寄存器中,从而使库代码无法lock住对它的读调用(如果在寄存器中则另一个线程可能会无意中修改该寄存器的值,而在内存中由于另一个线程没有访问权力所以不能修改)。
要声明变量必须在内存中就要用volatile修饰,这里修饰的是my_free_list,是free_list数组中的一个元素,而不是数组指针,所以volatile放在两个中间。

刻意制造临时对象

刻意制造临时对象。如string(“hello”);int(2);中的hello、2都是一个无名的临时对象。

静态常量整数成员在class内部直接初始化

class类中的const static integral data member,可以在类中直接赋初值。这是C++标准,integral泛指所有整型(char,long…)

宏定义

define __STL_TEMPLAE_NULL template<>

在GCC,VC6中允许不指定template<>就可以完成指定特定类型

define __STL_NULL_TMPL_ARGS <>

这种申明为了实现bound friend templates,也就是说,模板类的某个实现与友元类的某个实现一一对应。比如,操作符重载。
详见P33

需要注意的地方

T1 *pt1 = new(p) T1(value)

T1 *pt1 = new(p) T1(value)这叫placement new,在指针p(p是T1类型)所指向的内存空间创建一个类型为T1的对象。当然,构造的这个对象需要显示调用它的析构函数:pt1->~T1(),而不能用delete来完成。见more Effective C++ M8

set_new_handle(0)

set_new_handle(0)的意思是operator new申请一块内存失败时返回0,STL自己处理内存不足情况。
set_new_handle()的原型是:

typedef void (*new_handler)(); //定义返回值为空,参数为空的函数指针。
new_handler set_new_handler(new_handler p) throw();//operator new申请一块内存失败时调用p所指向的函数。并返回一个新的处理函数。

当operator new无法满足内存分配需求时,它会不断调用由set_new_handle()返回的new_handler函数,直到找到足够的内存。因此,应该妥善设计new_handler函数,一个设计良好的new_handler函数必须做以下事情:
1、删除其它无用的内存,使系统具有可以更多的内存可以使用,为下一步的内存申请作准备。
实现此策略的办法是:程序一开始执行就分配一大块内存,当new_handler被调用时,将它们释放还给程序使用。

2、设置另外一个new_handler。
如果当前的new_handler不能够做到更多的内存申请操作,或者它知道另外一个new_handler可以做到,则可以调用set_new_handler函数设置另外一个new_handler,这样在operator new下一次调用的时候,可以使用这个新的new_handler。

3、卸载new_handler,使operator new在下一次调用的时候,因为new_handler为空抛出内存申请异常。

4、new_handler抛出自定义的异常

5、不再返回,调用abort或者exit退出程序

ptrdiff_t

两个指针相减的结果的类型为ptrdiff_t,它是一种有符号整数类型。减法运算的值为两个指针在内存中的距离(以数组元素的长度为单位,而非字节),因为减法运算的结果将除以数组元素类型的长度。所以该结果与数组中存储的元素的类型无关。

size_t是unsigned类型,用于指明数组长度或下标,它必须是一个正数,std::size_t.设计size_t就是为了适应多个平台,其引入增强了程序在不同平台上的可移植性。

ptrdiff_t是signed类型,用于存放同一数组中两个指针之间的差距,它可以使负数,std::ptrdiff_t.同上,使用ptrdiff_t来得到独立于平台的地址差值.

size_type是unsigned类型,表示容器中元素长度或者下标,vector::size_type i = 0;

difference_type是signed类型,表示迭代器差距,vector:: difference_type = iter1-iter2.前二者位于标准类库std内,后二者专为STL对象所拥有。

操作符重载p38

int& operator*()const
{
return (int&)m_i
}

(int&)m_i它告诉编译器,你确实要将const int转为non-const lvalue。
这样方便对象作为左值。如果不明确的转换可能会报警告或错误。

迭代器是前闭后开区间表示[ )

所谓前闭后开[first,last),就是说整个范围从first开始,知道last-1结束。这样使得算法的循环设计干净利落。

for(;first != last; ++first) {//...}

function call 操作符( operator() )

如果你针对某个class进行operator()重载,它就会成为一个仿函数。可以代表函数指针,也可以代表一整组操作。

template<class T>
struct plus{
T operator()(const T& x,const T& y) const{return x + y;}
};

上面就是一个最简单的仿函数,它还不具备配给能力。
但是可以这样用了:

plus<int> plusobj;
int a = plusobj(2,3);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值