常用序列式容器包括vector、list、deque。本篇文章就来评析它们的迭代器,不同自增方式效率的不同。
在看这篇文章之前,大家可以先看看这篇文章:【C++】自增运算符重载及其效率问题-CSDN博客,了解一下之前得出的结果。前面的文章其中一个结论是,在自定义类型的自增(自减)运算符重载时,++i
往往比i++
效率更高。这篇文章旨在验证这一点。
测试代码:
#include <bits/stdc++.h>
#include <synchapi.h>
using namespace std;
int main(){
vector<int>v(20000,1);//这里依次换为其他容器即可,其他部分不需要变
double start,end;//记录时间
for (int k = 0; k < 5; ++k) {//重复测试5次
start=clock();
for (auto i=v.begin();i!=v.end();++i){
for (auto j=v.begin();j!=v.end();++j){
;
}
}
end=clock();
cout<<format("++i共耗时{:.2f}秒",(end-start)/1000)<<endl;//++i耗时
Sleep(2000);
start=clock();
for (auto i=v.begin();i!=v.end();i++){
for (auto j=v.begin();j!=v.end();j++){
;
}
}
end=clock();
cout<<format("i++共耗时{:.2f}秒",(end-start)/1000)<<endl<<endl;//i++耗时
}
return 0;
}
注意!如果没有用万能头文件的话,则需包含好相应的头文件,比如clock()
是<ctime>
,vector
是<vector>
。
vector迭代器实测
vector应该是大家最熟悉的序列式容器了。在这里将其迭代器的自增运算符展示在这里。后面的容器也是一样,不再赘述。
源代码(补充一下,vector的迭代器直接继承通用迭代器的设计,它的自增操作并没有包含在<stl_vector.h>里面,而是在<stl_iterator.h>里面):
_GLIBCXX20_CONSTEXPR
__normal_iterator&
operator++() _GLIBCXX_NOEXCEPT
{
++_M_current;
return *this;
}
_GLIBCXX20_CONSTEXPR
__normal_iterator
operator++(int) _GLIBCXX_NOEXCEPT
{ return __normal_iterator(_M_current++); }
测试结果:
可以看到,vector的i++
比++i
更耗时。
list迭代器实测
list容器实现了链表。
源代码:
_Self&
operator++() _GLIBCXX_NOEXCEPT
{
_M_node = _M_node->_M_next;
return *this;
}
_Self
operator++(int) _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
_M_node = _M_node->_M_next;
return __tmp;
}
测试结果:
可以看到,list的i++
比++i
更耗时。
deque迭代器实测
deque容器实现了双端队列。
源代码:
_Self&
operator++() _GLIBCXX_NOEXCEPT
{
++_M_cur;
if (_M_cur == _M_last)
{
_M_set_node(_M_node + 1);
_M_cur = _M_first;
}
return *this;
}
_Self
operator++(int) _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
++*this;
return __tmp;
}
测试结果:
可以看到,deque的i++
比++i
更耗时。
结果分析
可以看到,vector、list、deque的测试结果与上一篇文章的分析结果一致,均为i++
比++i
更耗时,从它们的源代码中也印证了这一点。因此,如果以后需要写迭代器自增(自减也是一样)的话,推荐使用++i
的方式。