Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用STL队列的循环队列?_C++_Stl_Queue - Fatal编程技术网

C++ 使用STL队列的循环队列?

C++ 使用STL队列的循环队列?,c++,stl,queue,C++,Stl,Queue,我在互联网上搜索了一段时间,但似乎找不到这个问题的答案 我打算使用stl::queue进行一些模拟。我想知道是否可以使用stl::queue创建一个循环队列?据我所知,stl::queue是线性的,默认情况下不是循环的 如果这是可能的,是否有任何实现参考,我可以参考 谢谢。std::deque被相当仔细地定义为一个线性队列。它的设计并不真正适合循环队列 特别是,它将队列分成许多大小相等的块,因此如果队列是合理平衡的(即,平均而言,数据的消耗速度与数据的生成速度差不多),通常会丢弃块并准备好重新使

我在互联网上搜索了一段时间,但似乎找不到这个问题的答案

我打算使用stl::queue进行一些模拟。我想知道是否可以使用stl::queue创建一个循环队列?据我所知,stl::queue是线性的,默认情况下不是循环的

如果这是可能的,是否有任何实现参考,我可以参考


谢谢。

std::deque
被相当仔细地定义为一个线性队列。它的设计并不真正适合循环队列

特别是,它将队列分成许多大小相等的块,因此如果队列是合理平衡的(即,平均而言,数据的消耗速度与数据的生成速度差不多),通常会丢弃块并准备好重新使用,因此可以在最小堆碎片的情况下长时间使用一个块

为了实现这一点,deque(至少正常情况下)使用两级存储机制。也就是说,它有一个可扩展的指针数组,每个指针指向一个包含实际数据的大小相等的块

然而,对于循环缓冲区,这是毫无意义和不必要的。对于循环缓冲区,通常在创建内存块时分配内存块,并继续使用相同的内存块,直到销毁它。在这种情况下,deque使用的两级存储只是为每个访问添加了额外的间接级别,而没有完成任何有用的操作

对于循环缓冲区,您还可以使用一块平坦的内存来保存数据,并在该内存块中创建/销毁对象。下面是我不久前编写的一个简单实现:

#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC

template <class T>
class circular_buffer {
    T *data;
    unsigned read_pos;
    unsigned write_pos;
    unsigned in_use;
    const unsigned capacity;
public:
    circular_buffer(unsigned size) :
        data((T *)operator new(size * sizeof(T))),
        read_pos(0),
        write_pos(0),
        in_use(0),
        capacity(size)
    {}

    void push(T const &t) {
        // ensure there's room in buffer:
        if (in_use == capacity) 
            pop();

        // construct copy of object in-place into buffer
        new(&data[write_pos++]) T(t);
        // keep pointer in bounds.
        write_pos %= capacity;
        ++in_use;
    }

    // return oldest object in queue:
    T front() {
        return data[read_pos];
    }

    // remove oldest object from queue:
    void pop() { 
        // destroy the object:
        data[read_pos++].~T();

        // keep pointer in bounds.
        read_pos %= capacity;
        --in_use;
    }
  
~circular_buffer() {
    // first destroy any content
    while (in_use != 0)
        pop();

    // then release the buffer.
    operator delete(data); 
}

};

#endif
\ifndef CBUFFER\u H\u公司
#定义CBUFFER_H_公司
模板
类循环缓冲区{
T*数据;
未签名读取位置;
未签名写入位置;
未签字的在用;
常数无符号容量;
公众:
循环缓冲区(无符号大小):
数据((T*)运算符新建(大小*大小(T)),
读取位置(0),
写入位置(0),
在使用中(0),
容量(大小)
{}
无效推力(T常数和T){
//确保缓冲区中有空间:
如果(在用==容量)
pop();
//将对象的副本就地构造到缓冲区中
新(&data[write_pos++])T(T);
//将指针保持在边界内。
写入位置%=容量;
++在用;
}
//返回队列中最早的对象:
T前面(){
返回数据[读取位置];
}
//从队列中删除最旧的对象:
void pop(){
//销毁对象:
数据[read_pos++].~T();
//将指针保持在边界内。
读取位置%=容量;
--在用;
}
~circular_buffer(){
//首先销毁任何内容
while(正在使用!=0)
pop();
//然后释放缓冲区。
操作员删除(数据);
}
};
#恩迪夫

如果您可以使用Boost库,那么已经有一个类模板实现了
front()
back()
push_back()
pop_front()
成员函数,因此可以用作容器适配器的底层容器:

#include <queue>
#include <boost/circular_buffer.hpp>
#include <cassert>

template<typename T>
using Queue = std::queue<T, boost::circular_buffer<T>>;

auto main() -> int {
   Queue<int> q(boost::circular_buffer<int>(3)); // capacity of the queue is 3

   q.push(0);
   q.push(1);
   q.push(2);
   assert(q.front() == 0);
   assert(q.back() == 2);

   q.push(3);
   assert(q.front() == 1);
   assert(q.back() == 3);

   q.pop();
   assert(q.front() == 2); 
   assert(q.back() == 3);
}
#包括
#包括
#包括
模板
使用Queue=std::Queue;
auto main()->int{
队列q(boost::circular_buffer(3));//队列的容量为3
q、 推(0);
q、 推(1);
q、 推(2);
断言(q.front()==0);
断言(q.back()==2);
q、 推(3);
断言(q.front()==1);
断言(q.back()==3);
q、 pop();
断言(q.front()==2);
断言(q.back()==3);
}

正确,
std::queue
就是这样。但是你希望你的“循环队列”如何工作呢?谢谢你的回复。这就是我所困惑的,是否可以使用
std::queue
实现循环队列。互联网上有很多循环队列,但它没有利用
std::queue
。据我所知,循环队列会重新连接队列的末端,因此在对象退出队列时不会浪费内存空间。您可以通过使用
std::deque
并在每次添加新项时删除第一个元素来伪造它,该项会将大小推过指定的缓冲区限制。不像真正的循环缓冲区那么便宜,但是非常容易写。你的意思是你想要一个循环(又名环)缓冲区吗?你提前知道最大尺寸吗?Boost有一个循环缓冲区:我重复一遍,不,
std::queue
就是它。它不是一个循环队列,无法将自身转换为循环队列。std::list将