为什么Vector back()方法是用迭代器实现的
reference back()
{ // return last element of mutable sequence
return (*(end() - 1));
}
而不是...... ...
return (*(_Myfirst + size()));
此问题的背景:
我最近一直在努力优化一些遗留代码(分配器实现),并注意到std::vector::back()
花费了大量时间。所以我做了一些使用不同集合的实验(Vector vs List vs Deque),因为back()
基本上是检索集合中的最后一个元素所以我还将vector::back()
与vector[size()-1]
进行了比较
这是我用来测试的代码:
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
#include <boost/timer/timer.hpp>
int RandomNumber () { return (rand()%100); }
void doVector( std::vector<int>& test_vec )
{
std::cout << "vect back() = " << test_vec.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_vec.back();
}
}
void doVector2( std::vector<int>& test_vec )
{
std::cout << "vect [size()-1] = " << test_vec[test_vec.size()-1] << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_vec[test_vec.size()-1];
}
}
void doList( std::vector<int>& test_vec )
{
std::list<int> test_list(test_vec.begin(),test_vec.end());
std::cout << "list back() = " << test_list.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_list.back();
}
}
void doDeque( std::vector<int>& test_vec )
{
std::deque<int> test_deq(test_vec.begin(),test_vec.end());
std::cout << "Deque back() = " << test_deq.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_deq.back();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> test_vec(100);
std::generate(test_vec.begin(), test_vec.end(), RandomNumber );
doVector(test_vec);
doVector2(test_vec);
doList(test_vec);
doDeque(test_vec);
}
结果是:
删除了结果,因为我在发布时间内以秒为单位打开了调试/关闭优化 - 我应该看到
显然,我将从使用vect [size() - 1]中获得显着的收益,并且我还将通过在前面()使用vect [0]来获得。我意识到我将自己与矢量联系起来,但在短期内这是我选择的方向(快速获胜)。但是,它让我想到 - 为什么front()和back()的向量实现在引擎盖下使用效率较低的实现?
vect back()= 41 0.183862s wall,0.171601s user + 0.000000s system = 0.171601s CPU(93.3%)
vect [size() - 1] = 41 0.416969s wall,0.421203s user + 0.000000s system = 0.421203s CPU(101.0%)
list back()= 41 0.079119s wall,0.078001s user + 0.000000s system = 0.078001s CPU(98.6%)
Deque back()= 41 0.186574s wall,0.187201s user + 0.000000s system = 0.187201s CPU(100.3%)
显然,当我进行分析时,我正在查看错误的结果 - 因为这完全支持了实施的选择。向在此编辑之前看过这个的人致歉.....
答案 0 :(得分:4)
C ++规范定义了语义而不是实现。如果使用与规范建议不同的实现来实现std::vector<T, A>::back()
的实现很重要,那么实现应该做正确的事情!显然,它仍然需要提供正确的语义。
它被指定的基本原因可能来自原始实现:std::vector<T, A>
的迭代器类型只是T*
(它仍然是一个有效的实现,尽管它已经变得不合时宜了原因)。当代std::vector<T, A>
实现倾向于使用简单的指针包装器。
所有这一切,你看到的开销实际上应该优化,因为对于体面的编译器:你使用了什么优化标志?
答案 1 :(得分:1)
从你的问题_Myfirst + size()
我猜你正在使用MSVC
进行iterator
调试,你确定你正在使用release
版本进行测试,因为在{ {1}}构建debug
调试需要一些额外的时间,但在iterator
模式下,它们都需要相同的时间(至少在我的机器上使用release
)