Introduction to Queues in C++

Introduction to Queues

Hello there! Today, we will unveil Queues in coding, likening them to a line in a coffee shop or a queue of print requests. Queues in computer science are First-In, First-Out (FIFO) structures. Consider this example: you're at a theme park — the first person in line for the roller coaster gets on first. Today's lesson revolves around this straightforward yet powerful concept. So, let's dive in!

Implementing a Queue in C++

Let's explore the implementation of Queues in C++. An array or a linked list is ideal for implementing a Queue, but we'll showcase a simple array-based implementation for clarity. Let's define the Queue:

#include <iostream>
using namespace std;

class Queue {
    int front, rear, size, capacity;
    int* array;

public:
    Queue(int capacity) {
        this->capacity = capacity;  // Set the max size
        front = size = 0;  // Initialize front and size
        rear = capacity - 1; // Initialize rear
        array = new int[this->capacity];
    }

    // Destructor to clean up resources
    ~Queue() {
        delete[] array;
    }

    // Will return true if the Queue is full
    bool isFull() {
        return (size == capacity);
    }
    
    // Will return true if the Queue is empty
    bool isEmpty() {
        return (size == 0);
    }
};

In the Queue class above, the isFull() method checks if our queue is already at maximum capacity, and isEmpty() checks if the queue is empty.

Rule of Three for Queues

When implementing classes that manage dynamic memory in C++, the Rule of Three becomes crucial. This rule indicates that if a class requires a custom destructor, it likely also requires a user-defined copy constructor and copy assignment operator. This trio of special member functions ensures that objects manage their resources correctly, preventing memory leaks and undefined behavior during object copying or assignment.

Here's how the Rule of Three applies to our Queue implementation:

Queue(const Queue& other) : front(other.front), rear(other.rear), size(other.size), capacity(other.capacity) {
    array = new int[capacity];
    std::copy(other.array, other.array + capacity, array);
}

Queue& operator=(const Queue& other) {
    if (this != &other) {
        delete[] array;
        front = other.front;
        rear = other.rear;
        size = other.size;
        capacity = other.capacity;
        array = new int[capacity];
        std::copy(other.array, other.array + capacity, array);
    }
    return *this;
}

Copy Constructor Queue(const Queue& other): This constructor initializes a new Queue object using an existing Queue, copying all properties: front, rear, size, and capacity, as well as dynamically allocating a new array and copying the data from the original queue. This ensures that both queues maintain their data integrity independently without sharing memory.

Copy Assignment Operator Queue& operator=(const Queue& other): It checks for self-assignment before proceeding. The operator deletes the existing array memory of the target object, then copies the attributes and data from another Queue. Memory allocation and element copying ensure that the assigning queue's contents replace the existing queue's data safely and efficiently.

By implementing the Rule of Three, our Queue class avoids potential pitfalls associated with resource management, such as memory leaks or dangling pointers, and ensures that each Queue instance can be independently managed and safely destroyed.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal