C++ 向量vs德克算子[]

C++ 向量vs德克算子[],c++,vector,deque,C++,Vector,Deque,如果我们不断地在容器的前面和后面添加数据,那么就要在向量上选择数据。但是抵消呢? vector和deque的操作符[]是否工作相同?如果没有,哪一个更快?对于deque 下标接近向量的效率 Bjarne Stroustrup“C++编程语言”17.2.3 它并不完全相同,因为访问元素需要一个额外的间接寻址。在许多情况下,由于缓存未命中,这会导致额外的内存命中。因此,随机访问的速度可能要慢几个数量级(实际上,大约1000倍)。但是,这将对许多连续访问进行摊销,因此在实践中通常不会那么糟糕。Astd

如果我们不断地在容器的前面和后面添加数据,那么就要在向量上选择数据。但是抵消呢?
vector
deque
操作符[]
是否工作相同?如果没有,哪一个更快?

对于deque

下标接近向量的效率

Bjarne Stroustrup“C++编程语言”17.2.3

它并不完全相同,因为访问元素需要一个额外的间接寻址。在许多情况下,由于缓存未命中,这会导致额外的内存命中。因此,随机访问的速度可能要慢几个数量级(实际上,大约1000倍)。但是,这将对许多连续访问进行摊销,因此在实践中通常不会那么糟糕。

A
std::vector
t
元素的平面数组
std::deque
是一个大小相等的
T
数组。在这两种情况下,索引访问的复杂性都是O(1),但是
std::deque
需要做更多的工作来确定要访问的元素,并且还有一个指示。与之类似,
std::deque
上的迭代器需要进行多次检查(虽然算法可以通过识别分段结构来优化这一点,使开销非常小。因此,如果需要经常使用下标运算符,
std::deque
可能是一个错误的选择,并且在前面插入/删除时移动
std::vector
中元素的成本可能会有所抵消

仅解释一下,在使用下标运算符的情况下,
std::deque
需要做什么:可以考虑执行以下操作:

T& deque<T>::operator[](size_t n) {
    n += this->first_element;
    size_t subarray = n / size_of_subarrays;
    size_t index    = n % size_of_subarrays;
    return this->subarrays[subarray][index];
}
T&deque::operator[](大小){
n+=此->第一个元素;
大小\u t子阵列=n/大小\u子阵列;
大小索引=子阵列大小的n%;
返回此->子数组[子数组][索引];
}

除法/模运算符不太可能太昂贵,因为几乎可以肯定地选择子数组的大小为2的幂,也就是说,它们基本上相当于位运算。

std::deque
类似于
std::vectors
的列表,因此如果您真的需要
[]
运算符,
std::vector
将更快地获取数据,但差异不大,所以您最好查看前后推送数据的频率,以确定是否需要
std::vector
std::deque


还有一件事,如果您使用获取容器索引的for循环,您最好使用
迭代器
,因为从
std::vector
std::deque
获取数据的速度差将不明显。

…在许多情况下,这反过来会由于缓存未命中而导致额外的内存命中。因此,它很可能是数量级(实际上,大约是1000倍)随机访问的速度较慢。但是,这将摊销许多连续访问,因此在实践中通常不会那么糟糕。是的,访问主内存而不是一级缓存的速度大约要慢1000倍。这就是为什么我们首先有缓存的原因。但正如我所说,一旦您访问了数据块,它通常会加载到内存中完全缓存,因此如果您随后访问邻近的元素,则缓存命中的可能性很高,因此访问速度更快。非常感谢,这类信息是我们真正需要了解的内容、使用时间和使用方法。这在某种程度上是显而易见的,但在许多情况下,将不同方面链接到一起也不是那么简单erIt是一个向量的向量,而不是向量的列表。关键的区别。@KonradRudolph没有解决关于实现的问题。但如果它是
vector
,那么
vector
deque
之间的区别就更不明显了。相关(但没有重复):如果我在容器的连续元素中循环,有没有关于如何使用deque提高循环速度的建议?使用迭代器会提高速度而不是抵消?如果有,你能帮我举一个例子说明如何在deque上实现迭代器,还是与在vectors中实现迭代器完全相同?@user2653125:i在DEQE上迭代是利用它的分段结构:而不是迭代遍历DEGO,单独地对每个子阵列进行迭代。很遗憾,DeGe不暴露这种分割结构,并且C++没有定义分段迭代器概念。然而,在DEQE上迭代的主要问题是增加I。terator需要检查迭代器是否已到达段的末尾。不太可能的分支或计算是否更便宜,很难预测,您需要进行测量。谢谢。如果由于我的算法,我只想在前面添加一个,并在一个方向上完全迭代容器,那么创建自己版本的链表而不是向量或deque?这会显著改变我的算法的性能吗?或者有其他更好的容器用于此目的吗?@user2653125:我希望在
std::deque
上迭代比在
std::list
上迭代更快,但这需要测量deque通常比在向量上迭代要慢。理想的数据结构应该是一个deque,通过使用分段迭代器来暴露其内部分段结构,并在迭代deque的算法中考虑到这种分段:它在迭代过程中具有几乎高效的访问和良好的ins行为在前端和末端插入。我会使用deque,看看它是否太慢。