I'm trying to implement a queue data structure in C++ using a circular array.
Please give recommendations on how I can improve this code. Also, is my array growth strategy good? I'm doubling the array when the buffer is full. (Try to remain in C++ 11 because, well that's a restriction I have to follow atm).
Sorry for the lack of comments in advance LoL (this is a rushed implementation).
#include <iostream>
#include <utility>
template <typename T>
class Queue {
public:
Queue() : data(nullptr), len(0), front(0), cap(0)
{
}
~Queue()
{
this->Clear();
}
Queue(const Queue& rhs) : Queue()
{
if (rhs.data) {
this->data = new T[rhs.cap];
this->cap = rhs.cap;
this->len = rhs.len;
this->front = rhs.front;
for (size_t i = 0; i < len; ++i) {
this->data[i] = rhs.data[i];
}
}
}
Queue(Queue&& rhs) : data(rhs.data), cap(rhs.cap), len(rhs.len), front(rhs.front)
{
rhs.data = nullptr;
}
Queue& operator=(Queue rhs)
{
swap(*this, rhs);
return *this;
}
size_t GetLength() const { return len; }
const T& GetFront() const { return data[front]; }
void Enqueue(const T& val)
{
if (len == cap) {
size_t oldCap = cap;
if (cap == 0) cap = 1;
cap *= 2;
T* newBuff = new T[cap];
for (size_t i = 0; i < len; ++i) {
size_t idx = (front + i) % oldCap;
newBuff[i] = data[idx];
}
front = 0;
data = newBuff;
}
data[(front + len) % cap] = val;
++len;
}
T Dequeue()
{
T val = std::move(data[front]);
front = (front + 1) % cap;
--len;
return val;
}
void Clear()
{
delete[] data;
data = nullptr;
this->cap = this->len = this->front = 0;
}
friend
std::ostream& operator<< (std::ostream& out, const Queue& q)
{
out << "Queue{";
for (size_t i = 0; i < q.len; ++i) {
size_t idx = (q.front + i) % q.cap;
out << q.data[idx];
if (i < q.len - 1) out << ", ";
}
out << "}";
return out;
}
friend
void swap(Queue& lhs, Queue& rhs)
{
std::swap(lhs.data, rhs.data);
std::swap(lhs.len, rhs.len);
std::swap(lhs.cap, rhs.cap);
std::swap(lhs.front, rhs.front);
}
private:
T* data;
size_t len;
size_t cap;
size_t front;
};
int main()
{
Queue < int > a;
a.Enqueue( 5 ); // add 5
a.Enqueue ( 6 ); // add 6
std::cout << a; // prints Queue{5, 6}
a.Clear(); // empties the Queue
std::cout << a; // prints Queue{}
}
```
main()
function in your code showing how this class can be used. You can edit it further to show the use of the rest of the functions \$\endgroup\$