C++ vector STL实现详解

本文详细解析了C++ STL中的vector实现,包括其内存布局、成员变量及GDB调试技巧。通过分析vector的源代码,阐述了_M_impl、_M_start、_M_finish、_M_end_of_storage等成员的作用,并展示了如何在GDB中查看vector的内容。文章还讨论了不同版本STL库的位置和差异,以及GDB中查看string和smart_ptr的方法。
摘要由CSDN通过智能技术生成


0.前言

  早前使用gdb调试特别不习惯: 1)没有图形界面IDE(比如Visual Studio)的强大功能:边打断点边代码跟进,退出断点保存,可以随时查看当前变量数据,对stl变量显示友好。2)gdb打印输出的内容有时难以理解,比如gdb只会打印出stl相关容器、复杂的类对象,智能指针的成员数据,而不会做格式化内容输出。比如原生gdb打印输出vector变量:

p v  # v为vector变量,初始化为vector<int> v(10, 1),直接print打印输出内容如下
$1 = {
  <_Vector_base<int, std::allocator<int> >> = {
    _M_impl = {
      <allocator<int>> = {
        <new_allocator<int>> = {<No data fields>}, <No data fields>},
      members of _Vector_base<int, std::allocator<int> >::_Vector_impl:
      _M_start = 0x100501ef0,
      _M_finish = 0x100501f18,
      _M_end_of_storage = 0x100501f18
    }
  }, <No data fields>}

  可以看到,vector成员变量仅有_M_impl, 而_M_impl成员变量又包含_M_start, _M_finish, _M_end_of_storage。不难推测:vector数据位于一块堆内存中,_M_start指向其分配的内存,_M_finish表示有效数据的结束位置,由于vector是动态数据,真正内存分配大小会大于实际使用,因为得考虑后期数据的增长,会预留内存,_M_end_of_storage指向的就是分配内存的结束位置。要想看vector对应的数据内容,需要复杂的gdb语句:

print *(v._M_impl._M_start)@v.size()

  发现用好gdb还是需要稍微了解下各种stl容器内存布局,而且stl容器也没有想象中的复杂,难懂主要是stl库用了各种高级模板封装和宏定义,本文以vector的标准库stl实现作为说明,vector还是个比较综合的例子,stl的其他容器比如string、map过程类似。想要配置对应的gdb请移动到《gdb调试配置》

1.stl库位置

  stl标准库不同版本差异很大,实现版本有HP STL、PJ STL、 SGI STL(侯捷的《STL源码剖析》分析的版本)等,而且stl库大致分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。安装了c++编译环境后,会安装上相应的stl库文件。mac系统下,代码#include <vector>语句包含的vector库下会是以下几种中的一种:

  1. /usr/include/c++/4.2.1/vector # mac/linux # 系统stl库位置
  2. /usr/local/Cellar/gcc/6.4.0/include/c++/6.4.0/vector # 安装GNU的gcc自带的stl库
  3. /Library/Developer/CommandLineTools/usr/include/c++/v1/vector # mac系统下xcode编译clang自带stl库

  其中第3种,是clang编译器自带的stl,文件即为定义文件,如果使用clang编译会包含改版本的vector实现,成员变量为__begin_、__end_、__end_cap_,与前面是有差别的,同样gdb打印如下:

$1 = {
  <std::__1::__vector_base<int, std::__1::allocato<int> >> = {
    <std::__1::__vector_base_common<true>> = {<No data fields>},
    members of std::__1::__vector_base<int, std::__1::allocator<int> >:
    __begin_ = 0x100300d00,
    __end_ = 0x100300d28,
    __end_cap_ = {
      <std::__1::__libcpp_compressed_pair_imp<int*, std::__1::allocator<int>, 2>> = {
        <std:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值