如何将 std::queue 转换为 std::vector

How to convert std::queue to std::vector

我需要使用双打队列,因为它作为有序容器具有良好的特性。我想将此队列传递给接受向量的 class 构造函数。如果我直接这样做,我会收到以下错误:

candidate constructor not viable: no known conversion from 'std::queue' to 'std::vector &' for 2nd argument

如何将队列转换为向量?

我认为没有任何直接的方法可用。 因此,这可以通过将元素一个一个地添加到向量中来实现。

std::vector<int> v;
while (!q.empty())
{
    v.push_back(q.front());
    q.pop();
}

请注意,此后队列将为空。

正如@David 在评论中所建议的那样,最好避免复制队列元素(特别是当包含的对象很大时很有帮助)。使用 emplace_back()std::move() 来达到同样的效果:

v.emplace_back(std::move(q.front()));

std::vector 有一个 constructor taking a pair of iterators,所以如果你能够遍历队列,你就会被设置。

借用 this question 的答案,您确实可以通过子类化 std::queue:

来做到这一点
template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
    typedef typename Container::const_iterator const_iterator;

    const_iterator begin() const { return this->c.begin(); }                                                                               
    const_iterator end() const { return this->c.end(); }
};

(注意我们只允许 const 迭代;为了问题的目的,我们不需要允许修改元素的迭代器。)

有了这个,很容易构造一个vector:

#include <queue>
#include <vector>

using namespace std;

template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
    typedef typename Container::const_iterator const_iterator;

    const_iterator begin() const { return this->c.begin(); }                                                                               
    const_iterator end() const { return this->c.end(); }
};

int main() {
    iterable_queue<int> int_queue;
    for(int i=0; i<10; ++i)
        int_queue.push(i);

    vector<int> v(int_queue.begin(), int_queue.end());
    return 0;
}

对 queue_like 行为和类似向量的行为进行建模的正确容器是 std::deque

这有以下优点:

  1. 双端队列两端的恒定时间插入和删除

  2. 能够在不破坏双端队列的情况下迭代元素

std::deque 支持 begin()end() 方法,这意味着您可以直接构造一个向量(具有兼容的值类型)。

#include <vector>
#include <deque>

class AcceptsVectors
{
public:
  AcceptsVectors(std::vector<double> arg);
};

int main()
{
    std::deque<double> myqueue;

    auto av = AcceptsVectors({myqueue.begin(), myqueue.end()});
}

queuevector 的非突变转换是不可能的。

这只是一种避免将std::queue复制到std::vector的方法。用不用就交给你了

场地

std::queue 是容器适配器。默认情况下,内部 containerstd::deque,但您也可以将其设置为 std::vector。幸运的是,保存这个容器的成员变量被标记为 protected。因此,您可以通过子类化 queue.

来破解它

解决方案 (!)

template<typename T>
struct my_queue : std::queue<T, std::vector<T>>
{
  using std::queue<T, std::vector<T>>::queue;
  // in G++, the variable name is `c`, but it may or may not differ
  std::vector<T>& to_vector () { return this->c; }
};

就是这样!!

用法

my_queue<int> q;
q.push(1);
q.push(2);
std::vector<int>& v = q.to_vector();

Demo.