C++ allocator使用场景下p/q/r变量关联与代码运行逻辑疑问
变量关联与循环逻辑说明
1. p、q、r三个指针的关系
三个都是指向allocator<string>分配的内存区域的string*类型指针,分工明确:
- p:是分配的5个string内存块的固定起始基地址,定义时加了const修饰,全程不会改变指向,用来标记内存块的起点,最后释放内存也是用这个地址。
- q:是「已构造对象的尾后指针」,初始值等于p(起始地址),每次调用
alloc.construct构造完一个对象后就自增1,永远指向下一个可以构造新对象的空闲位置,所有已经构造完成的对象都在[p, q)这个左闭右开区间里。 - r:是临时遍历指针,每次遍历前都会被重置为p(起始地址),用来挨个访问
[p, q)区间里已经构造好的对象,本身不会影响p和q的指向。
2. do...while循环的运行逻辑
你提到的循环代码如下:
do { cout<< "here" << *r << endl; } while (++r != q);
do...while的特性是先执行循环体,再做终止条件判断,运行逻辑拆解:
- 循环启动前r已经被赋值为p,也就是指向第一个已构造对象的地址
- 先执行循环体:打印当前r指向的对象内容
- 执行
++r,让r指向下一个相邻的内存地址 - 判断自增后的r是不是等于q(尾后指针):
- 不等于:继续下一轮循环
- 等于:终止循环
整个循环刚好遍历完[p, q)区间内所有的已构造对象,不会遗漏也不会越界访问还没构造的内存。
3. 结合完整代码的运行流程对应输出
顺着代码执行顺序拆解:
- 调用
alloc.allocate(5)分配了能存5个string的未初始化内存,p固定指向这块内存的起始地址 - q初始等于p,连续三次调用
construct构造对象,每次构造完q自增:- 第一次构造空string,q变为p+1
- 第二次构造10个'c'组成的string,q变为p+2
- 第三次构造"hi"字符串,q变为p+3
此时已构造对象的区间是[p, p+3),q等于p+3
- r被赋值为p,执行第一个do...while循环:
- 第一次循环:打印*r(空string,无可见输出),r自增为p+1,判断p+1 != p+3,继续
- 第二次循环:打印*r(10个c),r自增为p+2,判断p+2 != p+3,继续
- 第三次循环:打印*r("hi"),r自增为p+3,判断p+3 == p+3,终止循环
这部分对应输出前两行的cccccccccc和hi,空字符串打印无可见内容所以没有出现在输出结果里。
- 打印
done,然后执行destroy循环把所有已构造的对象销毁,q回到p的位置 - 重新给q赋值为p,r也重置为p,连续两次construct构造对象后q变为p+2,已构造区间是
[p, p+2) - 执行第二个带"here"的do...while循环:
- 第一次循环:打印
here加*r(10个a),r自增为p+1,判断p+1 != p+2,继续 - 第二次循环:打印
here加*r("hi again"),r自增为p+2,判断p+2 == p+2,终止循环
这部分对应输出最后两行的hereaaaaaaaaaa和herehi again
- 第一次循环:打印
- 最后调用
deallocate释放p指向的内存块,程序结束。
内容的提问来源于stack exchange,提问作者moey
相关产品推荐
相关产品推荐

