繁体   English   中英

在 std::vector 中实现 back()

[英]Implementation of back() in std::vector

为什么 Vector back() 方法是用迭代器来实现的

reference back()
{   // return last element of mutable sequence
    return (*(end() - 1));
}

而不是像...

return (*(_Myfirst + size()));

这个问题的背景:

我最近一直在优化一些遗留代码(分配器实现),并注意到在std::vector::back()中花费了大量时间。 所以我使用不同的 collections(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] 中获得显着收益,此外,我还将通过在 front() 上使用 vect[0] 获得更多收益。 我意识到我将自己与矢量联系在一起,但在短期内这是我选择的方向(快速获胜)。 但是,这让我想到 - 为什么 front() 和 back() 的向量实现在底层使用效率较低的实现?


vect back() = 41 0.183862s 墙,0.171601s 用户 + 0.000000s 系统 = 0.171601s CPU (93.3%)

vect [size()-1] = 41 0.416969s 墙,0.421203s 用户 + 0.000000s 系统 = 0.421203s CPU (101.0%)

list back() = 41 0.079119s 墙,0.078001s 用户 + 0.000000s 系统 = 0.078001s CPU (98.6%)

Deque back() = 41 0.186574s 墙,0.187201s 用户 + 0.000000s 系统 = 0.187201s CPU (100.3%)

很明显,当我进行分析时,我看到了错误的结果——因为这完全支持了实现的选择。 向在此编辑之前查看此内容的人道歉......

C ++规范定义了语义而不是实现。 如果对std::vector<T, A>::back()的实现很重要std::vector<T, A>::back()是使用与规范建议不同的实现来实现的,那么实现应该只做正确的事! 显然,它仍然需要提供正确的语义。

它被指定的基本原因可能来自原始实现: std::vector<T, A>的迭代器类型只是一个T* (它仍然是一个有效的实现,尽管由于各种原因而变得不合时宜) 。 当代std::vector<T, A>实现倾向于使用一个简单的指针包装器。

总而言之,您看到的开销实际上应该进行优化,因为对于体面的编译器:您使用了哪些优化标志?

从您的问题_Myfirst + size()我想你正在使用具有iterator调试的MSVC ,你确定你正在使用release版本进行测试,因为在debug构建iterator调试需要一些额外的时间,但在release模式下他们都采取相等的时间(至少在我使用MSVC 2010机器上)

因为您只获取值而不使用它,所以编译器会将这些代码优化为无操作(使用 -O2)。

因此,比较这两种操作的时间是不准确的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM