C++的STL模板库中提供了3种容器类:vector,list,deque
对于这三种容器,在觉得好用的同时,经常会让我们困惑应该选择哪一种来实现我们的逻辑。
在少量数据操作的程序中随便哪一种用起来感觉差别并不是很大,
但是当数据达到一定数量后,会明显感觉性能上有很大差异。
本文就试图从介绍,以及性能比较两个方面来讨论这个问题。
vector - 会自动增长的数组
vector又称为向量数组,他是为了解决程序中定义的数组是
不能动态改变大小这个缺点而出现的。
一般程序实现是在类创建的时候同时创建一个定长数组,
随着数据不断被写入,一旦数组被填满,则重新开辟一块更大的内存区,
把原有的数据复制到新的内存区,抛弃原有的内存,如此反复。
由于程序自动管理数组的增长,对于我们程序员来说确实轻松了不少,
只管把数据往里面插就行了,当然把物理内存和虚拟内存插爆掉了
就是操作系统来找你麻烦了:-)
vector由于数组的增长只能向前,所以也只提供了后端插入和后端删除,
也就是push_back和pop_back。当然在前端和中间要操作数据也是可以的,
用insert和erase,但是前端和中间对数据进行操作必然会引起数据块的移动,
这对性能影响是非常大的。
对于所有数组来说,最大的优势就是随机访问的能力。
在vector中,提供了at和[]运算符这两个方法来进行随机访问。
由于每个数据大小相同,并且无间隔地排列在内存中,
所以要对某一个数据操作,只需要用一个表达式就能直接计算出地址:
address = base + index * datasize
同样,对vector进行内存开辟,初始化,清除都是不需要花大力气的,
从头到尾都只有一块内存。
不能动态改变大小这个缺点而出现的。
一般程序实现是在类创建的时候同时创建一个定长数组,
随着数据不断被写入,一旦数组被填满,则重新开辟一块更大的内存区,
把原有的数据复制到新的内存区,抛弃原有的内存,如此反复。
由于程序自动管理数组的增长,对于我们程序员来说确实轻松了不少,
只管把数据往里面插就行了,当然把物理内存和虚拟内存插爆掉了
就是操作系统来找你麻烦了:-)
vector由于数组的增长只能向前,所以也只提供了后端插入和后端删除,
也就是push_back和pop_back。当然在前端和中间要操作数据也是可以的,
用insert和erase,但是前端和中间对数据进行操作必然会引起数据块的移动,
这对性能影响是非常大的。
对于所有数组来说,最大的优势就是随机访问的能力。
在vector中,提供了at和[]运算符这两个方法来进行随机访问。
由于每个数据大小相同,并且无间隔地排列在内存中,
所以要对某一个数据操作,只需要用一个表达式就能直接计算出地址:
address = base + index * datasize
同样,对vector进行内存开辟,初始化,清除都是不需要花大力气的,
从头到尾都只有一块内存。
list - 擅长插入删除的链表
有黑必有白,世界万物都是成对出现的。
链表对于数组来说就是相反的存在。
数组本身是没有动态增长能力的(程序中也必须重新开辟内存来实现),
而链表强悍的就是动态增长和删除的能力。
但对于数组强悍的随机访问能力来说的话,链表却很弱。
list是一个双向链表的实现。
为了提供双向遍历的能力,list要比一般的数据单元多出两个指向前后的指针。
这也是没办法的,毕竟现在的PC内存结构就是一个大数组,
链表要在不同的环境中实现自己的功能就需要花更多空间。
list提供了push_back,push_front,pop_back,pop_front四个方法
来方便操作list的两端数据的增加和删除,不过少了vector的at和[]运算符的
随机访问数据的方法。并不是不能实现,而是list的设计者
并不想让list去做那些事情,因为他们会做得非常差劲。
对于list来说,清除容器内所有的元素是一件苦力活,
因为所有数据单元的内存都不连续,list只有一个一个遍历来删除。
链表对于数组来说就是相反的存在。
数组本身是没有动态增长能力的(程序中也必须重新开辟内存来实现),
而链表强悍的就是动态增长和删除的能力。
但对于数组强悍的随机访问能力来说的话,链表却很弱。
list是一个双向链表的实现。
为了提供双向遍历的能力,list要比一般的数据单元多出两个指向前后的指针。
这也是没办法的,毕竟现在的PC内存结构就是一个大数组,
链表要在不同的环境中实现自己的功能就需要花更多空间。
list提供了push_back,push_front,pop_back,pop_front四个方法
来方便操作list的两端数据的增加和删除,不过少了vector的at和[]运算符的
随机访问数据的方法。并不是不能实现,而是list的设计者
并不想让list去做那些事情,因为他们会做得非常差劲。
对于list来说,清除容器内所有的元素是一件苦力活,
因为所有数据单元的内存都不连续,list只有一个一个遍历来删除。
deque - 拥有vector和list两者优点的双端队列
黑与白,处于这两个极端之间的就是令人愉悦的彩色了。
deque作为vector和list的结合体,确实有着不凡的实力。
STL的deque的实现没有怎么去看过,不过根据我自己的猜测,
应该是把数组分段化,在分段的数组上添加指针来把所有段连在一起,
最终成为一个大的数组。
deque和list一样,提供了push_back,push_front,
pop_back,pop_front四个方法。可以想象,如果要对deque的两端进行操作,
也就是要对第一段和最后一段的定长数组进行重新分配内存区,
由于分过段的数组很小,重新分配的开销也就不会很大。
deque也和vector一样,提供了at和[]运算符的方法。
要计算出某个数据的地址的话,虽然要比vector麻烦一点,
但效率要比list高多了。
首先和list一样进行遍历,每次遍历的时候累积每段数组的大小,
当遍历到某个段,而且baseN <= index < baseN + baseN_length的时候,
通过address = baseN + baseN_index就能计算出地址
由于分过段的后链表的长度也不是很长,所以遍历对于
整体性能的影响就微乎其微了。
看起来deque很无敌吧,不过deque和希腊神话的阿吉里斯一样,
再怎么强大也是有自己的弱点的,之后的测试数据中就能看到了。
deque作为vector和list的结合体,确实有着不凡的实力。
STL的deque的实现没有怎么去看过,不过根据我自己的猜测,
应该是把数组分段化,在分段的数组上添加指针来把所有段连在一起,
最终成为一个大的数组。
deque和list一样,提供了push_back,push_front,
pop_back,pop_front四个方法。可以想象,如果要对deque的两端进行操作,
也就是要对第一段和最后一段的定长数组进行重新分配内存区,
由于分过段的数组很小,重新分配的开销也就不会很大。
deque也和vector一样,提供了at和[]运算符的方法。
要计算出某个数据的地址的话,虽然要比vector麻烦一点,
但效率要比list高多了。
首先和list一样进行遍历,每次遍历的时候累积每段数组的大小,
当遍历到某个段,而且baseN <= index < baseN + baseN_length的时候,
通过address = baseN + baseN_index就能计算出地址
由于分过段的后链表的长度也不是很长,所以遍历对于
整体性能的影响就微乎其微了。
看起来deque很无敌吧,不过deque和希腊神话的阿吉里斯一样,
再怎么强大也是有自己的弱点的,之后的测试数据中就能看到了。
性能竞技场
为了能更好地进行比较,我们让静态数组(程序中写死的)和
动态数组(程序中new出来的)也参加了部分竞技。
竞技项目:
动态数组(程序中new出来的)也参加了部分竞技。
竞技项目:
- 初始化:对于静态和动态数组,逐一赋值,对于容器,push_back插入
- 前向遍历:从0到n-1,每个数据自加1
- 后向遍历:从n-1到0,每个数据自减1
- 随机访问:在0到n-1中,随机抽取一定数量的数据进行读取
- 后端插入:用push_back在后端插入一定数量的数据
- 后端移除:用pop_back在后端移除一定数量的数据
- 前端插入:用push_front在前端插入一定数量的数据
- 前端移除:用pop_front在前端移除一定数量的数据
- 中间插入:用insert在中间插入一定数量的数据
- 中间移除:用erase在中间移除一定数量的数据
- 反初始化:对于静态和动态数组,ZeroMemory删除所有数据,对于容器,调用clear方法
规则:
- vector,list,deque都调用默认的构造函数来创建
- 数组和容器的数据项都是1,000,000个
- 前端和后端插入的数据项是10,000个
- 前端和后端删除的数据项是10,000个
- 随机访问的数据项是10,000个
- 数据类型采用int型
- 计时采用RDTSC高精度计时器来计时
- 随机访问的数据的位置序列在测试前随机生成,所有数组和容器都采用这个序列
- 测试采用Debug版(Release版会对代码进行优化,可能会对测试产生一定的影响)
- 测试3次,取平均值
测试机配置:
Intel(R) Core(TM)2 CPU T7400 2.16GHz 2.16GHz
2.00GB内存
测试结果:(单位 秒)
Intel(R) Core(TM)2 CPU T7400 2.16GHz 2.16GHz
2.00GB内存
测试结果:(单位 秒)
测试项目 | 静态数组 | 动态数组 | vector | list | deque | 备注 |
初始化 | 0.00551 | 0.00461 | 0.207 | 1.30 | 0.352 | list每个数据项都有附加数据,速度稍慢了一些 |
前向遍历 | 0.00381 | 0.00549 | 0.0796 | 0.0756 | 0.0713 | |
后向遍历 | 0.00422 | 0.00478 | 0.885 | 0.879 | 0.690 | |
随机访问 | 0.000334 | 0.000342 | 0.00119 | 148 | 0.0115 | list把时间都耗在了找寻相应数据上 |
后端插入 | N/A | N/A | 0.00192 | 0.0128 | 0.00260 | |
后端移除 | N/A | N/A | 0.00131 | 0.0293 | 0.00194 | |
前端插入 | N/A | N/A | 10.2 | 0.0128 | 0.00547 | vector对前端操作很苦手啊 |
前端移除 | N/A | N/A | 10.3 | 0.0297 | 0.00135 | 同上 |
中间插入 | N/A | N/A | 195 | 187 | 764 | 看似万能的deque的最大弱点,因为复杂的结构导致中间数据操作带来的复杂性大大增加,体现在操作时间是其他两个的几倍 |
中间移除 | N/A | N/A | 195 | 209 | 753 | 同上 |
反初始化 | 0.00139 | 0.00290 | 0.0000106 | 0.693 | 0.305 | vector貌似是直接抛弃内存的,其他两个就没那么简单了 |
性能总结与使用建议
测试项目 | 静态数组 | 动态数组 | vector | list | deque |
初始化 | ★★★★★ | ★★★★★ | ★★★★☆ | ★★★☆☆ | ★★★★☆ |
前向遍历 | ★★★★★ | ★★★★★ | ★★★★☆ | ★★★★☆ | ★★★★☆ |
后向遍历 | ★★★★★ | ★★★★★ | ★★★★☆ | ★★★★☆ | ★★★★☆ |
随机访问 | ★★★★★ | ★★★★★ | ★★★★☆ | ★☆☆☆☆ | ★★★☆☆ |
后端插入 | N/A | N/A | ★★★★★ | ★★★★☆ | ★★★★★ |
后端移除 | N/A | N/A | ★★★★★ | ★★★★☆ | ★★★★★ |
前端插入 | N/A | N/A | ★★☆☆☆ | ★★★★☆ | ★★★★★ |
前端移除 | N/A | N/A | ★★☆☆☆ | ★★★★☆ | ★★★★★ |
中间插入 | N/A | N/A | ★★☆☆☆ | ★★☆☆☆ | ★☆☆☆☆ |
中间移除 | N/A | N/A | ★★☆☆☆ | ★★☆☆☆ | ★☆☆☆☆ |
反初始化 | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★☆ | ★★★★☆ |
一些使用上的建议:
Level 1 - 仅仅作为Map使用:采用静态数组
Level 2 - 保存定长数据,使用时也是全部遍历:采用动态数组(长度一开始就固定的话静态数组也行)
Level 3 - 保存不定长数组,需要动态增加的能力,侧重于寻找数据的速度:采用vector
Level 3 - 保存不定长数组,需要动态增加的能力,侧重于增加删除数据的速度:采用list
Level 4 - 对数据有复杂操作,即需要前后增删数据的能力,又要良好的数据访问速度:采用deque
Level 5 - 对数据中间的增删操作比较多:采用list,建议在排序的基础上,批量进行增删可以对运行效率提供最大的保证
Level 6 - 上述中找不到适合的:组合STL容器或者自己建立特殊的数据结构来实现
测试程序清单
>>>main.cpp<<<
0001 | #include <string> |
0002 | #include <iostream> |
0003 | #include <iomanip> |
0004 | #include <vector> |
0005 | #include <list> |
0006 | #include <set> |
0007 | #include <map> |
0008 | #include <deque> |
0009 | #include <algorithm> |
0010 | #include <windows.h> |
0011 | |
0012 | using namespace std; |
0013 | |
0014 | inline unsigned __int64 GetTick() |
0015 | { |
0016 | __asm RDTSC |
0017 | } |
0018 | |
0019 | // 定数の定義 |
0020 | const int ARRAY_SIZE = 1000 * 1000 * 1; |
0021 | const int INSERT_NUM = 1000 * 10; |
0022 | const int DELETE_NUM = INSERT_NUM; |
0023 | const int READ_RANDOM_NUM = 1000 * 10; |
0024 | const int VALUE_OFFSET = 0; |
0025 | typedef int TARGET_TYPE; |
0026 | typedef void (*FUNC)(); |
0027 | |
0028 | |
0029 | // グローバル変数の定義 |
0030 | __int64 g_second; |
0031 | int g_rand_list[READ_RANDOM_NUM]; |
0032 | TARGET_TYPE g_static_array[ARRAY_SIZE]; |
0033 | TARGET_TYPE* g_dynamic_array; |
0034 | TARGET_TYPE stub; |
0035 | std::vector <TARGET_TYPE> g_vector; |
0036 | std::list <TARGET_TYPE> g_list; |
0037 | std::deque <TARGET_TYPE> g_deque; |
0038 | |
0039 | |
0040 | // 関数定義 |
0041 | __int64 GetPerSecondTick(); |
0042 | double GetSecond(__int64 beginTick); |
0043 | void init(); |
0044 | void uninit(); |
0045 | void start(); |
0046 | void clear(); |
0047 | void check(); |
0048 | void calctime(FUNC f, string msg); |
0049 | void DebugOut(string str); |
0050 | void AddOneBySelf(TARGET_TYPE& tt); |
0051 | void SubOneBySelf(TARGET_TYPE& tt); |
0052 | |
0053 | |
0054 | void StaticArrayCheck(); |
0055 | void DynamicArrayCheck(); |
0056 | void VectorCheck(); |
0057 | void ListCheck(); |
0058 | void DequeCheck(); |
0059 | |
0060 | |
0061 | void StaticArrayInit(); |
0062 | void DynamicArrayInit(); |
0063 | void VectorInit(); |
0064 | void ListInit(); |
0065 | void DequeInit(); |
0066 | |
0067 | |
0068 | void StaticArrayUninit(); |
0069 | void DynamicArrayUninit(); |
0070 | void VectorUninit(); |
0071 | void ListUninit(); |
0072 | void DequeUninit(); |
0073 | |
0074 | |
0075 | void StaticArrayForEach(); |
0076 | void DynamicArrayForEach(); |
0077 | void VectorForEach(); |
0078 | void ListForEach(); |
0079 | void DequeForEach(); |
0080 | |
0081 | |
0082 | void StaticArrayForEachRight(); |
0083 | void DynamicArrayForEachRight(); |
0084 | void VectorForEachRight(); |
0085 | void ListForEachRight(); |
0086 | void DequeForEachRight(); |
0087 | |
0088 | |
0089 | void StaticArrayForEachRandom(); |
0090 | void DynamicArrayForEachRandom(); |
0091 | void VectorForEachRandom(); |
0092 | void ListForEachRandom(); |
0093 | void DequeForEachRandom(); |
0094 | |
0095 | |
0096 | void VectorInsertAtBack(); |
0097 | void ListInsertAtBack(); |
0098 | void DequeInsertAtBack(); |
0099 | |
0100 | |
0101 | void VectorDeleteAtBack(); |
0102 | void ListDeleteAtBack(); |
0103 | void DequeDeleteAtBack(); |
0104 | |
0105 | |
0106 | void VectorInsertAtFront(); |
0107 | void ListInsertAtFront(); |
0108 | void DequeInsertAtFront(); |
0109 | |
0110 | |
0111 | void VectorDeleteAtFront(); |
0112 | void ListDeleteAtFront(); |
0113 | void DequeDeleteAtFront(); |
0114 | |
0115 | |
0116 | |
0117 | void VectorInsertAtMiddle(); |
0118 | void ListInsertAtMiddle(); |
0119 | void DequeInsertAtMiddle(); |
0120 | |
0121 | |
0122 | void VectorDeleteAtMiddle(); |
0123 | void ListDeleteAtMiddle(); |
0124 | void DequeDeleteAtMiddle(); |
0125 | |
0126 | |
0127 | void init() |
0128 | { |
0129 | g_second = GetPerSecondTick(); |
0130 | g_dynamic_array = new TARGET_TYPE[ARRAY_SIZE]; |
0131 | srand((int)GetTick()); |
0132 | for (int i = 0; i < READ_RANDOM_NUM; i++) |
0133 | { |
0134 | g_rand_list[i] = MulDiv(ARRAY_SIZE - 1, rand(), RAND_MAX); |
0135 | } |
0136 | |
0137 | calctime(StaticArrayInit, "StaticArrayInit: "); |
0138 | calctime(DynamicArrayInit, "DynamicArrayInit: "); |
0139 | calctime(VectorInit, "VectorInit: "); |
0140 | calctime(ListInit, "ListInit: "); |
0141 | calctime(DequeInit, "DequeInit: "); |
0142 | cout << endl; |
0143 | } |
0144 | |
0145 | void uninit() |
0146 | { |
0147 | calctime(StaticArrayUninit, "StaticArrayUninit: "); |
0148 | calctime(DynamicArrayUninit, "DynamicArrayUninit: "); |
0149 | calctime(VectorUninit, "VectorUninit: "); |
0150 | calctime(ListUninit, "ListUninit: "); |
0151 | calctime(DequeUninit, "DequeUninit: "); |
0152 | cout << endl; |
0153 | } |
0154 | |
0155 | void check() |
0156 | { |
0157 | StaticArrayCheck(); |
0158 | DynamicArrayCheck(); |
0159 | VectorCheck(); |
0160 | ListCheck(); |
0161 | DequeCheck(); |
0162 | } |
0163 | |
0164 | void start() |
0165 | { |
0166 | calctime(StaticArrayForEach, "StaticArrayForEach: "); |
0167 | calctime(DynamicArrayForEach, "DynamicArrayForEach: "); |
0168 | calctime(VectorForEach, "VectorForEach: "); |
0169 | calctime(ListForEach, "ListForEach: "); |
0170 | calctime(DequeForEach, "DequeForEach: "); |
0171 | cout << endl; |
0172 | |
0173 | calctime(StaticArrayForEachRight, "StaticArrayForEachRight: "); |
0174 | calctime(DynamicArrayForEachRight, "DynamicArrayForEachRight: "); |
0175 | calctime(VectorForEachRight, "VectorForEachRight: "); |
0176 | calctime(ListForEachRight, "ListForEachRight: "); |
0177 | calctime(DequeForEachRight, "DequeForEachRight: "); |
0178 | cout << endl; |
0179 | |
0180 | calctime(StaticArrayForEachRandom, "StaticArrayForEachRandom: "); |
0181 | calctime(DynamicArrayForEachRandom, "DynamicArrayForEachRandom: "); |
0182 | calctime(VectorForEachRandom, "VectorForEachRandom: "); |
0183 | calctime(ListForEachRandom, "ListForEachRandom: "); |
0184 | calctime(DequeForEachRandom, "DequeForEachRandom: "); |
0185 | cout << endl; |
0186 | |
0187 | |
0188 | calctime(NULL, ""); |
0189 | calctime(NULL, ""); |
0190 | calctime(VectorInsertAtBack, "VectorInsertAtBack: "); |
0191 | calctime(ListInsertAtBack, "ListInsertAtBack: "); |
0192 | calctime(DequeInsertAtBack, "DequeInsertAtBack: "); |
0193 | cout << endl; |
0194 | |
0195 | |
0196 | calctime(NULL, ""); |
0197 | calctime(NULL, ""); |
0198 | calctime(VectorDeleteAtBack, "VectorDeleteAtBack: "); |
0199 | calctime(ListDeleteAtBack, "ListDeleteAtBack: "); |
0200 | calctime(DequeDeleteAtBack, "DequeDeleteAtBack: "); |
0201 | cout << endl; |
0202 | |
0203 | |
0204 | |
0205 | calctime(NULL, ""); |
0206 | calctime(NULL, ""); |
0207 | calctime(VectorInsertAtFront, "VectorInsertAtFront: "); |
0208 | calctime(ListInsertAtFront, "ListInsertAtFront: "); |
0209 | calctime(DequeInsertAtFront, "DequeInsertAtFront: "); |
0210 | cout << endl; |
0211 | |
0212 | |
0213 | calctime(NULL, ""); |
0214 | calctime(NULL, ""); |
0215 | calctime(VectorDeleteAtFront, "VectorDeleteAtFront: "); |
0216 | calctime(ListDeleteAtFront, "ListDeleteAtFront: "); |
0217 | calctime(DequeDeleteAtFront, "DequeDeleteAtFront: "); |
0218 | cout << endl; |
0219 | |
0220 | |
0221 | |
0222 | calctime(NULL, ""); |
0223 | calctime(NULL, ""); |
0224 | calctime(VectorInsertAtMiddle, "VectorInsertAtMiddle: "); |
0225 | calctime(ListInsertAtMiddle, "ListInsertAtMiddle: "); |
0226 | calctime(DequeInsertAtMiddle, "DequeInsertAtMiddle: "); |
0227 | cout << endl; |
0228 | |
0229 | |
0230 | calctime(NULL, ""); |
0231 | calctime(NULL, ""); |
0232 | calctime(VectorDeleteAtMiddle, "VectorDeleteAtMiddle: "); |
0233 | calctime(ListDeleteAtMiddle, "ListDeleteAtMiddle: "); |
0234 | calctime(DequeDeleteAtMiddle, "DequeDeleteAtMiddle: "); |
0235 | cout << endl; |
0236 | } |
0237 | |
0238 | |
0239 | void clear() |
0240 | { |
0241 | delete g_dynamic_array; |
0242 | } |
0243 | |
0244 | |
0245 | |
0246 | |
0247 | |
0248 | void StaticArrayInit() |
0249 | { |
0250 | for (int i = 0; i < ARRAY_SIZE; i++) g_static_array[i] = i; |
0251 | } |
0252 | |
0253 | void DynamicArrayInit() |
0254 | { |
0255 | for (int i = 0; i < ARRAY_SIZE; i++) g_dynamic_array[i] = i; |
0256 | } |
0257 | |
0258 | void VectorInit() |
0259 | { |
0260 | for (int i = 0; i < ARRAY_SIZE; i++) g_vector.push_back(i); |
0261 | } |
0262 | |
0263 | void ListInit() |
0264 | { |
0265 | for (int i = 0; i < ARRAY_SIZE; i++) g_list.push_back(i); |
0266 | } |
0267 | |
0268 | void DequeInit() |
0269 | { |
0270 | for (int i = 0; i < ARRAY_SIZE; i++) g_deque.push_back(i); |
0271 | } |
0272 | |
0273 | |
0274 | |
0275 | |
0276 | |
0277 | void StaticArrayUninit() |
0278 | { |
0279 | ZeroMemory(g_static_array, ARRAY_SIZE * sizeof(TARGET_TYPE)); |
0280 | } |
0281 | |
0282 | void DynamicArrayUninit() |
0283 | { |
0284 | ZeroMemory(g_dynamic_array, ARRAY_SIZE * sizeof(TARGET_TYPE)); |
0285 | } |
0286 | |
0287 | void VectorUninit() |
0288 | { |
0289 | g_vector.clear(); |
0290 | } |
0291 | |
0292 | void ListUninit() |
0293 | { |
0294 | g_list.clear(); |
0295 | } |
0296 | |
0297 | void DequeUninit() |
0298 | { |
0299 | g_deque.clear(); |
0300 | } |
0301 | |
0302 | void StaticArrayForEach() |
0303 | { |
0304 | for (int i = 0; i < ARRAY_SIZE; i++) ++g_static_array[i]; |
0305 | } |
0306 | |
0307 | void DynamicArrayForEach() |
0308 | { |
0309 | for (int i = 0; i < ARRAY_SIZE; i++) ++g_dynamic_array[i]; |
0310 | } |
0311 | |
0312 | void VectorForEach() |
0313 | { |
0314 | for_each(g_vector.begin(), g_vector.end(), AddOneBySelf); |
0315 | } |
0316 | |
0317 | void ListForEach() |
0318 | { |
0319 | for_each(g_list.begin(), g_list.end(), AddOneBySelf); |
0320 | } |
0321 | |
0322 | void DequeForEach() |
0323 | { |
0324 | for_each(g_deque.begin(), g_deque.end(), AddOneBySelf); |
0325 | } |
0326 | |
0327 | void StaticArrayForEachRight() |
0328 | { |
0329 | for (int i = ARRAY_SIZE; i > 0; i--) --g_static_array[i - 1]; |
0330 | } |
0331 | |
0332 | void DynamicArrayForEachRight() |
0333 | { |
0334 | for (int i = ARRAY_SIZE; i > 0; i--) --g_dynamic_array[i - 1]; |
0335 | } |
0336 | |
0337 | void VectorForEachRight() |
0338 | { |
0339 | for_each(g_vector.rbegin(), g_vector.rend(), SubOneBySelf); |
0340 | } |
0341 | |
0342 | void ListForEachRight() |
0343 | { |
0344 | for_each(g_list.rbegin(), g_list.rend(), SubOneBySelf); |
0345 | } |
0346 | |
0347 | void DequeForEachRight() |
0348 | { |
0349 | for_each(g_deque.rbegin(), g_deque.rend(), SubOneBySelf); |
0350 | } |
0351 | |
0352 | |
0353 | void StaticArrayForEachRandom() |
0354 | { |
0355 | for (int i = 0; i < READ_RANDOM_NUM; i++) stub = g_static_array[g_rand_list[i]]; |
0356 | } |
0357 | |
0358 | void DynamicArrayForEachRandom() |
0359 | { |
0360 | for (int i = 0; i < READ_RANDOM_NUM; i++) stub = g_dynamic_array[g_rand_list[i]]; |
0361 | } |
0362 | |
0363 | void VectorForEachRandom() |
0364 | { |
0365 | for (int i = 0; i < READ_RANDOM_NUM; i++) stub = g_vector[g_rand_list[i]]; |
0366 | } |
0367 | |
0368 | void ListForEachRandom() |
0369 | { |
0370 | list<TARGET_TYPE>::iterator iter; |
0371 | |
0372 | for (int i = 0; i < READ_RANDOM_NUM; i++) |
0373 | { |
0374 | iter = g_list.begin(); |
0375 | for (int j = 0; j < g_rand_list[i]; j++) ++iter; |
0376 | stub = (*iter); |
0377 | } |
0378 | } |
0379 | |
0380 | void DequeForEachRandom() |
0381 | { |
0382 | for (int i = 0; i < READ_RANDOM_NUM; i++) stub = g_deque[g_rand_list[i]]; |
0383 | } |
0384 | |
0385 | |
0386 | |
0387 | void StaticArrayCheck() |
0388 | { |
0389 | for (int i = 0; i < ARRAY_SIZE; i++) |
0390 | { |
0391 | if (g_static_array[i] != (i + VALUE_OFFSET)) |
0392 | { |
0393 | cerr << "StaticArrayCheck NG:" << i << " = " << g_static_array[i] << endl; |
0394 | return; |
0395 | } |
0396 | } |
0397 | } |
0398 | |
0399 | void DynamicArrayCheck() |
0400 | { |
0401 | for (int i = 0; i < ARRAY_SIZE; i++) |
0402 | { |
0403 | if (g_dynamic_array[i] != (i + VALUE_OFFSET)) |
0404 | { |
0405 | cerr << "DynamicArrayCheck NG:" << i << " = " << g_dynamic_array[i] << endl; |
0406 | return; |
0407 | } |
0408 | } |
0409 | } |
0410 | |
0411 | void VectorCheck() |
0412 | { |
0413 | vector<TARGET_TYPE>::iterator iter; |
0414 | int i = 0; |
0415 | |
0416 | for (iter = g_vector.begin(); iter != g_vector.end(); ++iter, ++i) |
0417 | { |
0418 | if ((*iter) != (i + VALUE_OFFSET)) |
0419 | { |
0420 | cerr << "VectorCheck NG:" << i << " = " << (*iter) << endl; |
0421 | return; |
0422 | } |
0423 | } |
0424 | } |
0425 | |
0426 | void ListCheck() |
0427 | { |
0428 | list<TARGET_TYPE>::iterator iter; |
0429 | int i = 0; |
0430 | |
0431 | for (iter = g_list.begin(); iter != g_list.end(); ++iter, ++i) |
0432 | { |
0433 | if ((*iter) != (i + VALUE_OFFSET)) |
0434 | { |
0435 | cerr << "ListCheck NG:" << i << " = " << (*iter) << endl; |
0436 | return; |
0437 | } |
0438 | } |
0439 | } |
0440 | |
0441 | void DequeCheck() |
0442 | { |
0443 | deque<TARGET_TYPE>::iterator iter; |
0444 | int i = 0; |
0445 | |
0446 | for (iter = g_deque.begin(); iter != g_deque.end(); ++iter, ++i) |
0447 | { |
0448 | if ((*iter) != (i + VALUE_OFFSET)) |
0449 | { |
0450 | cerr << "DequeCheck NG:" << i << " = " << (*iter) << endl; |
0451 | return; |
0452 | } |
0453 | } |
0454 | } |
0455 | |
0456 | |
0457 | |
0458 | void VectorInsertAtBack() |
0459 | { |
0460 | for (int i = 0; i < INSERT_NUM; i++) g_vector.push_back((TARGET_TYPE)0); |
0461 | } |
0462 | |
0463 | void ListInsertAtBack() |
0464 | { |
0465 | for (int i = 0; i < INSERT_NUM; i++) g_list.push_back((TARGET_TYPE)0); |
0466 | } |
0467 | |
0468 | void DequeInsertAtBack() |
0469 | { |
0470 | for (int i = 0; i < INSERT_NUM; i++) g_deque.push_back((TARGET_TYPE)0); |
0471 | } |
0472 | |
0473 | void VectorDeleteAtBack() |
0474 | { |
0475 | for (int i = 0; i < DELETE_NUM; i++) g_vector.pop_back(); |
0476 | } |
0477 | |
0478 | void ListDeleteAtBack() |
0479 | { |
0480 | for (int i = 0; i < DELETE_NUM; i++) g_list.pop_back(); |
0481 | } |
0482 | |
0483 | void DequeDeleteAtBack() |
0484 | { |
0485 | for (int i = 0; i < DELETE_NUM; i++) g_deque.pop_back(); |
0486 | } |
0487 | |
0488 | |
0489 | |
0490 | |
0491 | void VectorInsertAtFront() |
0492 | { |
0493 | for (int i = 0; i < INSERT_NUM; i++) g_vector.insert(g_vector.begin(), (TARGET_TYPE)0); |
0494 | } |
0495 | |
0496 | void ListInsertAtFront() |
0497 | { |
0498 | for (int i = 0; i < INSERT_NUM; i++) g_list.push_front((TARGET_TYPE)0); |
0499 | } |
0500 | |
0501 | void DequeInsertAtFront() |
0502 | { |
0503 | for (int i = 0; i < INSERT_NUM; i++) g_deque.push_front((TARGET_TYPE)0); |
0504 | } |
0505 | |
0506 | |
0507 | |
0508 | void VectorDeleteAtFront() |
0509 | { |
0510 | for (int i = 0; i < DELETE_NUM; i++) g_vector.erase(g_vector.begin()); |
0511 | } |
0512 | |
0513 | void ListDeleteAtFront() |
0514 | { |
0515 | for (int i = 0; i < DELETE_NUM; i++) g_list.pop_front(); |
0516 | } |
0517 | |
0518 | void DequeDeleteAtFront() |
0519 | { |
0520 | for (int i = 0; i < DELETE_NUM; i++) g_deque.pop_front(); |
0521 | } |
0522 | |
0523 | |
0524 | void VectorInsertAtMiddle() |
0525 | { |
0526 | vector<TARGET_TYPE>::iterator iter; |
0527 | for (int i = 0; i < INSERT_NUM; i++) |
0528 | { |
0529 | iter = g_vector.begin(); |
0530 | for (unsigned int j = 0; j < g_vector.size() / 2; j++) ++iter; |
0531 | g_vector.insert(iter, (TARGET_TYPE)0); |
0532 | } |
0533 | } |
0534 | |
0535 | void ListInsertAtMiddle() |
0536 | { |
0537 | list<TARGET_TYPE>::iterator iter; |
0538 | for (int i = 0; i < INSERT_NUM; i++) |
0539 | { |
0540 | iter = g_list.begin(); |
0541 | for (unsigned int j = 0; j < g_list.size() / 2; j++) ++iter; |
0542 | g_list.insert(iter, (TARGET_TYPE)0); |
0543 | } |
0544 | } |
0545 | |
0546 | void DequeInsertAtMiddle() |
0547 | { |
0548 | deque<TARGET_TYPE>::iterator iter; |
0549 | for (int i = 0; i < INSERT_NUM; i++) |
0550 | { |
0551 | iter = g_deque.begin(); |
0552 | for (unsigned int j = 0; j < g_deque.size() / 2; j++) ++iter; |
0553 | g_deque.insert(iter, (TARGET_TYPE)0); |
0554 | } |
0555 | } |
0556 | |
0557 | |
0558 | void VectorDeleteAtMiddle() |
0559 | { |
0560 | vector<TARGET_TYPE>::iterator iter; |
0561 | for (int i = 0; i < DELETE_NUM; i++) |
0562 | { |
0563 | iter = g_vector.begin(); |
0564 | for (unsigned int j = 0; j < g_vector.size() / 2; j++) ++iter; |
0565 | g_vector.erase(iter); |
0566 | } |
0567 | } |
0568 | |
0569 | void ListDeleteAtMiddle() |
0570 | { |
0571 | list<TARGET_TYPE>::iterator iter; |
0572 | for (int i = 0; i < DELETE_NUM; i++) |
0573 | { |
0574 | iter = g_list.begin(); |
0575 | for (unsigned int j = 0; j < g_list.size() / 2; j++) ++iter; |
0576 | g_list.erase(iter); |
0577 | } |
0578 | } |
0579 | |
0580 | void DequeDeleteAtMiddle() |
0581 | { |
0582 | deque<TARGET_TYPE>::iterator iter; |
0583 | for (int i = 0; i < DELETE_NUM; i++) |
0584 | { |
0585 | iter = g_deque.begin(); |
0586 | for (unsigned int j = 0; j < g_deque.size() / 2; j++) ++iter; |
0587 | g_deque.erase(iter); |
0588 | } |
0589 | } |
0590 | |
0591 | |
0592 | |
0593 | |
0594 | void calctime(FUNC f, string msg) |
0595 | { |
0596 | __int64 t1; |
0597 | |
0598 | if (f != NULL) |
0599 | { |
0600 | t1 = GetTick(); |
0601 | (*f)(); |
0602 | // cerr << msg << GetSecond(t1) << endl; |
0603 | cout << GetSecond(t1) << ", "; |
0604 | } |
0605 | else |
0606 | { |
0607 | // cerr << msg << "N/A" << endl; |
0608 | cout << "N/A, "; |
0609 | } |
0610 | } |
0611 | |
0612 | __int64 GetPerSecondTick() |
0613 | { |
0614 | __int64 t1; |
0615 | |
0616 | t1 = GetTick(); |
0617 | Sleep(1000); |
0618 | return (GetTick() - t1); |
0619 | } |
0620 | |
0621 | double GetSecond(__int64 beginTick) |
0622 | { |
0623 | return (double)(GetTick() - beginTick) / (double)g_second; |
0624 | } |
0625 | |
0626 | void AddOneBySelf(TARGET_TYPE& tt) |
0627 | { |
0628 | ++tt; |
0629 | } |
0630 | |
0631 | void SubOneBySelf(TARGET_TYPE& tt) |
0632 | { |
0633 | --tt; |
0634 | } |
0635 | |
0636 | void DebugOut(string str) |
0637 | { |
0638 | cerr << str << endl; |
0639 | } |
0640 | |
0641 | |
0642 | int main(char** argv, int argc) |
0643 | { |
0644 | // 初期化 |
0645 | init(); |
0646 | |
0647 | // 実行開始 |
0648 | start(); |
0649 | |
0650 | // チェック |
0651 | check(); |
0652 | |
0653 | // 資源回収 |
0654 | uninit(); |
0655 | |
0656 | // クリア |
0657 | clear(); |
0658 | |
0659 | return 0; |
0660 | } |
0661 |