【C++】常用序列式容器迭代器自增效率实测

常用序列式容器包括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++); }

测试结果:

image-20240325185952415

可以看到,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;
}

测试结果:

image-20240325185827181

可以看到,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;
}

测试结果:

image-20240325190245648

可以看到,deque的i++++i更耗时。

结果分析

可以看到,vector、list、deque的测试结果与上一篇文章的分析结果一致,均为i++++i更耗时,从它们的源代码中也印证了这一点。因此,如果以后需要写迭代器自增(自减也是一样)的话,推荐使用++i的方式。

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要为自定义的C序列容器添加迭代器,需要定义一个迭代器结构体,包含容器的元素类型、指向当前位置的指针(或索引)、向前移动迭代器的函数指针、向后移动迭代器的函数指针、获取当前元素的函数指针等等。接下来,需要在容器结构体中添加一个函数,用于返回迭代器对象。该函数应该接受容器的指针作为参数,并返回一个迭代器对象。 下面是一个简单的示例代码,用于向自定义的C序列容器中添加迭代器: ```c typedef struct { int* data; int size; } my_container; typedef struct { int* ptr; int index; } my_iterator; my_iterator* create_iterator(my_container* c) { my_iterator* it = malloc(sizeof(my_iterator)); it->ptr = c->data; it->index = 0; return it; } void advance_forward(my_iterator* it) { it->ptr++; it->index++; } void advance_backward(my_iterator* it) { it->ptr--; it->index--; } int get_current_element(my_iterator* it) { return *(it->ptr); } // 容器结构体 typedef struct { int* data; int size; my_iterator* (*begin)(my_container*); } my_sequence; my_iterator* begin(my_container* c) { return create_iterator(c); } my_sequence* create_sequence(int* data, int size) { my_sequence* s = malloc(sizeof(my_sequence)); s->data = data; s->size = size; s->begin = begin; return s; } int main() { int data[] = {1, 2, 3, 4, 5}; my_sequence* s = create_sequence(data, 5); my_iterator* it = s->begin(s); while (it->index < s->size) { printf("%d\n", get_current_element(it)); advance_forward(it); } return 0; } ``` 在上面的示例代码中,我们定义了一个名为`my_iterator`的迭代器结构体,它包含一个指向当前元素的指针和一个当前位置的索引。然后,我们定义了一些用于操作迭代器的函数,例如向前移动、向后移动和获取当前元素。接下来,我们定义了一个名为`my_sequence`的容器结构体,它包含一个指向数据的指针和数据的大小。然后,我们在容器结构体中定义了一个函数`begin`,该函数返回容器迭代器对象。最后,我们在`main`函数中使用容器迭代器进行了简单的测试。 当然,以上只是一个简单的示例,实际情况中需要根据具体的需求来定义迭代器的结构体和操作函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forgotten Legend

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值