vector内部实现问题

dodo_yy 2009-05-05 11:14:16
不说闲话,先发程序和结果.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
int start = 1;
vector<int> v1(100);
v1.push_back(1); //
cout<<v1.size()<<endl; // 101
cout<<v1.capacity()<<endl; // 200
int end = 1;
cout<<sizeof(v1)<<endl; // 12
cout<<sizeof(start)<<endl; // 4
cout<<&start-&end<<endl; //9

cout<<"After reserve"<<endl;
v1.reserve(1000);
cout<<v1.size()<<endl; //101
cout<<v1.capacity()<<endl; //1000
cout<<sizeof(v1)<<endl; //12
system("PAUSE");
return 0;
}



/***********************************
****** DEV C++ *******
101
200
12
4
9
After reserve
101
1000
12
**********************************/

/*******************************
******** visual c++ ********
101
150
20
4
10
After reserve
101
1000
20
******************************/

我们问题主要是
sizeof(v1) = 12,20 那个是什么大小?? 难道是类的大小。
还有 &start-&end 为什么是9,10 ?这个为什么不是8,或者其他.
哪位从vector内部实现的角度给我讲讲?
...全文
878 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
nuoshueihe 2009-05-07
  • 打赏
  • 举报
回复
其中vector的size()是具体元素数目
而capacity是采用红黑树来实现的,所以大小一般是2^n
如果第一次为一个元素,则都是1
再放一个2^1 为2,
再放一个2^2 为4;
这时候检测size,如果size<=capacity 如果成立的话,就不再分配空间
否则,就在前一次的基础上增加一倍
也就是我们一般测量时capacity要大一些的原因

quanheng2755 2009-05-07
  • 打赏
  • 举报
回复
vc6.0中的结果是这样的:
101
200
16
4
5
After reserve
101
1000
16
请按任意键继续. . .
hjjdebug 2009-05-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 beyond071 的回复:]
(3)&start和&end都是int类型的指针,他们之间的差距都是以4字节的指针为单位的。
&start - &end的值要看编译器为临时变量分配存储空间的方式,虽然两者中间隔着一个vector,但其间隔并不是vector的大小。
例如在VS2008下,即使start和end是两个连续的临时变量,他们的内存地址也并不是紧挨着的,即&start - &end != 1。
[/Quote]
[Quote=引用 17 楼 dodo_yy 的回复:]
谢谢各位了,特别是hejinjing_tom_com, beyond071
基本是明白了.
sizeof(v1) 就是这个类对象v1的大小.不同编译器实现有所不同.
(int)&end - (int)&start 实际上应该是sizeof(v1) + 4,
&end - &start 就是 sizeof(v1)/4 + 1;

还有点问题,我的用的vs 2005和DEV 4.9.9,两个那个结果还是有出入
&end -&start 都不等于 sizeof(v1)/4 + 1

9 != 12/4 + 1;
10 != 20/4 + 1;

这里还有什么东西没弄清楚?
[/Quote]
我认为它们的内存地址分配还是紧挨着的。只是分配策略不同。
在vs2005 下实验了一下,两个int 变量其间距离是12 byte, 就是说,一个int 占4byte, 留出了8 byte做缝隙。成了12 byte, 而vc6 下默认是以4byte 对齐。
再来看start,end 之间的距离, 是40 bytes. 它的组成是:
4(start)+8(缝隙)+20(v)+8(缝隙)= 40.
dev c++ 我没有环境,就不妄加腿断了。
hjjdebug 2009-05-06
  • 打赏
  • 举报
回复
补充一下9楼。
&start - &end 其值是20 byte, 中间的内存分配正是int start, 4byte, vector v1 大小 16 byte 之和。
beyond071 2009-05-06
  • 打赏
  • 举报
回复
STL实现的差异:
(1)dev C++ 中STL使用的预留策略是,如果初始化N个元素,如果再压入数据导致重分配,那么就预先分配2N个空间;
visual C++ 中STL使用的预留策略是,如果初始化N个元素,如果再压入数据导致重分配那么就预先分配N+N/2个空间;

(2)sizeof(v1)相当于sizeof(class vector),其大小具体多少要看这个vector的实现中用到多少成员。

(3)&start和&end都是int类型的指针,他们之间的差距都是以4字节的指针为单位的。
&start - &end的值要看编译器为临时变量分配存储空间的方式,虽然两者中间隔着一个vector,但其间隔并不是vector的大小。
例如在VS2008下,即使start和end是两个连续的临时变量,他们的内存地址也并不是紧挨着的,即&start - &end != 1。
ysysbaobei 2009-05-06
  • 打赏
  • 举报
回复
Paradin 2009-05-06
  • 打赏
  • 举报
回复
顶ls
hjjdebug 2009-05-06
  • 打赏
  • 举报
回复
ls 笔误, 一个指针占4bytes, 3个指针占12 bytes
hjjdebug 2009-05-06
  • 打赏
  • 举报
回复
[Quote=引用楼主 dodo_yy 的帖子:]
我们问题主要是
sizeof(v1) = 12,20 那个是什么大小?? 难道是类的大小。
还有 &start-&end 为什么是9,10 ?这个为什么不是8,或者其他.
哪位从vector内部实现的角度给我讲讲?
[/Quote]

我以我的vc6 环境说明一下楼主问题,其它环境也可以触类旁通。
先看代码及输出(标在旁边了)

#pragma pack(1)
#include <iostream>
#include <vector>

using namespace std;

int main()
{
int start = 1;
vector<int> v1(100);
v1.push_back(1); //
cout<<v1.size()<<endl; // 101
cout<<v1.capacity()<<endl; // 200
int end = 1;
cout<<sizeof(v1)<<endl; // 16
cout<<sizeof(start)<<endl; // 4
printf("%d\n",(unsigned int)&start-(unsigned int)&end); //20
cout<<&start-&end<<endl; //5

cout<<"After reserve"<<endl;
v1.reserve(1000);
cout<<v1.size()<<endl; //101
cout<<v1.capacity()<<endl; //1000
cout<<sizeof(v1)<<endl; //16
system("PAUSE");
return 0;
}



1. sizeof(v1) = 16. 这个大小就是类的大小。当然也就是类对象的大小。
vector 中有如下成员
_A allocator;
iterator _First, _Last, _End;
allocator 是一个对象,占一个byte, 被调整成4 byte. 不同的编译器,可能令allocator 占0,占1,或占4bytes
iterator 是分配器指针, 对vector而言可暂时理解为int 型指针, 3个指针占4 bytes.
故一个vector 对象占 16 bytes.

2. &start - & end 为什么是5
我把&start 强制转化为整型用 printf 输出,得到大小是20(看代码)。
若不转为整型也是5.
用cout 将地址转换为整型也是20
所以我们知道,这个5代表的是指针的个数,5个指针的大小就是20bytes
dodo_yy 2009-05-06
  • 打赏
  • 举报
回复
谢谢各位了,特别是hejinjing_tom_com, beyond071
基本是明白了.
sizeof(v1) 就是这个类对象v1的大小.不同编译器实现有所不同.
(int)&end - (int)&start 实际上应该是sizeof(v1) + 4,
&end - &start 就是 sizeof(v1)/4 + 1;

还有点问题,我的用的vs 2005和DEV 4.9.9,两个那个结果还是有出入
&end -&start 都不等于 sizeof(v1)/4 + 1

9 != 12/4 + 1;
10 != 20/4 + 1;

这里还有什么东西没弄清楚?
九桔猫 2009-05-06
  • 打赏
  • 举报
回复
可以看下《STL源码剖析》 先了解下原理,然后看下你所用编译器STL中vector的实现
xike2002 2009-05-06
  • 打赏
  • 举报
回复
vs7中的结果是这样的:
/***************************************
101
150
16
4
9
After reserve
101
1000
16
请按任意键继续. . .
****************************************/
Sou2012 2009-05-06
  • 打赏
  • 举报
回复
顶了
lpf000 2009-05-05
  • 打赏
  • 举报
回复
UP
dodo_yy 2009-05-05
  • 打赏
  • 举报
回复
我现在是这样理解的,vector模板类包括一个数据的指针,指向内存区域,当然这个类可能还有一些信息,如size
vector{T* data;int size,}
所以sizeof(v1) = 12,20之类的
他的capacity可以通过sizeof(*data) 算出来

如果这样想的话,&start-&end 应该也是12+4,20+4,为什么只有9,10.
dodo_yy 2009-05-05
  • 打赏
  • 举报
回复
&start-&end 那个具体怎么是9,10
v1这时候应该怎么去理解,如果大小是4的话,不是可以理解成一个指针了.
sizeof(v1)这个操作,对应的结构在C++语法中还可以做特殊处理么? 为什么不是4.
lingyin55 2009-05-05
  • 打赏
  • 举报
回复
sizeof(v1) = 12,20 那个是什么大小?? 难道是类的大小。

不是类的大小,这个属于容器实现的问题,包含容器的信息肯定需要空间存储,
而容器在不同的编译器实现又是不同,这个值的大小就是容器信息所占用的空间,
在不同的编译器上不同。
liliangbao 2009-05-05
  • 打赏
  • 举报
回复
帮顶!!!
fibbery 2009-05-05
  • 打赏
  • 举报
回复
sizeof是vector具化后的类实例所占用内存的大小,不包括动态分配的内存。
jackyjkchen 2009-05-05
  • 打赏
  • 举报
回复
各家的标准库实现其实是有差别的,vector的源文件挺大,看得眼花

64,664

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧