【问题标题】:Insertion in std::vector vs. insertion in std::deque插入 std::vector 与插入 std::deque
【发布时间】:2018-05-31 06:44:21
【问题描述】:

我正在解决2017 Advent of Code 中的谜题。有必要使用某种算法填充循环缓冲区。对于缓冲区实现,我首先使用向量,然后尝试使用双端队列。打印向量和队列的值时,我得到不同的结果。代码如下:

#include <iostream>
#include <vector>

void PrintBuffer(std::vector<int> a_CircularBuffer)
{
    for (std::vector<int>::iterator it = a_CircularBuffer.begin(); it != a_CircularBuffer.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

int main()
{
    std::vector<int> circularBuffer;
    circularBuffer.reserve(20);

    circularBuffer.push_back(0);
    circularBuffer.push_back(1);

    std::vector<int>::iterator currentPosition = circularBuffer.begin() + 1;

    for (int i = 2; i < 20; ++i) {
        int steps = 378;
        if (steps >= i) {
            steps = (steps % i);
        }    

        if ((circularBuffer.end() - currentPosition) <= steps) {
            currentPosition = circularBuffer.begin() + (((currentPosition - circularBuffer.begin()) + steps) % i);
            circularBuffer.insert(currentPosition, i);
        }
        else {
            currentPosition = currentPosition + steps;
            circularBuffer.insert(currentPosition, i);
        }
        PrintBuffer(circularBuffer);
    }
    return 0;
}

这是使用向量时的结果:

0 2 1
0 3 2 1 
0 3 2 4 1 
0 5 3 2 4 1 
0 6 5 3 2 4 1 
0 7 6 5 3 2 4 1 
0 7 6 8 5 3 2 4 1 
0 7 6 9 8 5 3 2 4 1 
0 10 7 6 9 8 5 3 2 4 1 
0 10 7 6 9 11 8 5 3 2 4 1 
0 10 7 6 9 11 8 5 3 2 4 12 1 
0 10 7 6 9 11 8 5 3 2 4 12 13 1 
0 10 7 6 9 11 8 5 3 2 4 12 14 13 1 
15 0 10 7 6 9 11 8 5 3 2 4 12 14 13 1 
...

这是使用 deque 时(只需将“vector”更改为“deque”并注释掉 circularBuffer.reserve(20) 行):

0 2 1 
0 3 2 1 
0 3 2 4 1 
0 5 3 2 4 1 
0 5 6 3 2 4 1 
0 5 6 7 3 2 4 1 
0 5 6 7 3 8 2 4 1 
0 5 6 7 3 9 8 2 4 1 
0 5 6 10 7 3 9 8 2 4 1 
0 5 6 10 7 3 9 8 11 2 4 1 
0 5 12 6 10 7 3 9 8 11 2 4 1 
0 5 12 6 13 10 7 3 9 8 11 2 4 1 
0 5 12 6 13 14 10 7 3 9 8 11 2 4 1 
0 5 12 6 13 14 10 7 3 15 9 8 11 2 4 1
...

为什么vector和deque的结果不同?

【问题讨论】:

    标签: c++ vector deque


    【解决方案1】:

    当您插入一个导致重新分配的元素时,您会得到未定义的行为,然后再次使用旧的迭代器。

    任何事情都有可能发生。

    使用索引来存储当前位置,它会以同样的方式工作。

    【讨论】:

    • 谢谢。是的,后来我使用索引来存储当前位置,它的工作方式与使用双端队列和迭代器相同。我只是在徘徊为什么矢量不同,我不知道这是一个未定义的行为。此外,当我执行类似 currentPosition = circularBuffer.insert(currentPosition, i) 的操作时,我得到的结果与以前相同。我认为这将“更新” currentPosition 迭代器。
    • 还有一件事,如果我保留了足够的空间(我确实做到了),应该不会重新分配,对吧?那么迭代器应该没问题,我猜?
    • 对于双端队列即使没有重新分配也是UB > 如果插入发生在序列的开头或结尾,则与该容器相关的所有迭代器都无效,但指针和引用仍然有效,指他们在通话之前提到的相同元素。如果插入发生在双端队列中的任何其他位置,则与此容器相关的所有迭代器、指针和引用都将失效。
    猜你喜欢
    • 2013-08-18
    • 2016-02-04
    • 2019-05-07
    • 2012-09-19
    • 2023-03-07
    • 2012-03-07
    • 2015-01-15
    • 2019-05-22
    • 2022-01-18
    相关资源
    最近更新 更多