首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用vector::iterator或at()迭代STL向量,哪个更快?

使用vector::iterator或at()迭代STL向量,哪个更快?
EN

Stack Overflow用户
提问于 2009-04-22 10:55:05
回答 11查看 75.5K关注 0票数 61

在性能方面,什么会更快?有什么不同吗?它依赖于平台吗?

代码语言:javascript
复制
//1. Using vector<string>::iterator:
vector<string> vs = GetVector();

for(vector<string>::iterator it = vs.begin(); it != vs.end(); ++it)
{
   *it = "Am I faster?";
}

//2. Using size_t index:
for(size_t i = 0; i < vs.size(); ++i)
{
   //One option:
   vs.at(i) = "Am I faster?";
   //Another option:
   vs[i] = "Am I faster?";
}
EN

回答 11

Stack Overflow用户

发布于 2009-04-22 10:57:41

使用迭代器会导致指针递增(用于递增)和取消引用为取消引用指针。

对于索引,增量应该同样快,但查找元素涉及加法(data pointer+index)和取消引用该指针,但差异应该是微不足道的。

at()还会检查索引是否在界限内,因此它可能会更慢。

500M迭代的基准测试结果,向量大小为10,使用gcc 4.3.3 (-O3),Linux2.6.29.1 x86_64:

at():9158ms

operator[]:4269ms

iterator:3914ms

YMMV,但是如果使用索引使代码更易读或更容易理解,您应该这样做。

2021年更新

在现代编译器中,所有选项实际上都是免费的,但迭代器在迭代方面稍好一些,并且更容易与范围循环(for(auto& x: vs))一起使用。

代码:

代码语言:javascript
复制
#include <vector>

void iter(std::vector<int> &vs) {
    for(std::vector<int>::iterator it = vs.begin(); it != vs.end(); ++it)
        *it = 5;
}

void index(std::vector<int> &vs) {
    for(std::size_t i = 0; i < vs.size(); ++i)
        vs[i] = 5;
}

void at(std::vector<int> &vs) {
    for(std::size_t i = 0; i < vs.size(); ++i)
        vs.at(i) = 5;
}

index()at()生成的程序集是相同的godbolt,但iter()的循环设置少了两条指令:

代码语言:javascript
复制
iter(std::vector<int, std::allocator<int> >&):
        mov     rax, QWORD PTR [rdi]
        mov     rdx, QWORD PTR [rdi+8]
        cmp     rax, rdx
        je      .L1
.L3:                              ; loop body
        mov     DWORD PTR [rax], 5
        add     rax, 4
        cmp     rax, rdx
        jne     .L3
.L1:
        ret
index(std::vector<int, std::allocator<int> >&):
        mov     rax, QWORD PTR [rdi]
        mov     rdx, QWORD PTR [rdi+8]
        sub     rdx, rax
        mov     rcx, rdx
        shr     rcx, 2
        je      .L6
        add     rdx, rax
.L8:                              ; loop body
        mov     DWORD PTR [rax], 5
        add     rax, 4
        cmp     rdx, rax
        jne     .L8
.L6:
        ret
票数 42
EN

Stack Overflow用户

发布于 2009-04-22 11:21:00

如果你不需要索引,就不要使用它。迭代器的概念是最好的。迭代器很容易优化,而直接访问则需要一些额外的知识。

索引是用于直接访问的。括号和at方法可以做到这一点。与[]不同的是,at会检查越界索引,因此速度会更慢。

信条是:不要索要你不需要的东西。这样编译器就不会为你不用的东西收费了。

票数 18
EN

Stack Overflow用户

发布于 2009-04-22 11:08:17

既然你关注的是效率,你应该意识到以下变化可能更有效:

代码语言:javascript
复制
//1. Using vector<string>::iterator:

vector<string> vs = GetVector();
for(vector<string>::iterator it = vs.begin(), end = vs.end(); it != end; ++it)
{
   //...
}

//2. Using size_t index:

vector<string> vs = GetVector();
for(size_t i = 0, size = vs.size(); i != size; ++i)
{
   //...
}

因为end/size函数只调用一次,而不是通过循环每次都调用。编译器很可能无论如何都会内联这些函数,但这种方式可以确保。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/776624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档