Dynamic Stack  «Prev  Next»
Lesson 3 Stack constructors
Objective Take a closer look at the ch_stack constructors.

C++ Stack Constructors

C++ stacks provide several constructors that allow flexible initialization depending on your needs. The default constructor `stack()` creates an empty stack using a `deque` as the underlying container by default. You can also specify a different underlying container type with the constructor `stack(const Container& cont = Container())`, which copies elements from an existing container. Additionally, the copy constructor `stack(const stack& other)` creates a new stack as a deep copy of another stack, while the move constructor `stack(stack&& other)` (C++11 onward) enables efficient transfer of ownership through move semantics. These constructors make `std::stack` both simple to use for basic LIFO operations and adaptable when more control over the underlying container is required.

Use Case 2 critique

Constructor overloads: what you’re really choosing

In the previous lesson, ch_stack was designed so the client can choose a stack capacity at construction time. In C++, that “choice” is expressed through constructor overloads: same class name, different parameter lists. The overload the compiler selects depends only on the arguments you pass at the call site.


Capacity constructor

If a client knows the maximum number of elements up front, a “capacity” constructor makes the intent explicit:

ch_stack data(1000);        // capacity: 1000 elements
ch_stack more_data(2 * n);  // capacity: 2*n elements

Two additional constructor shapes

  1. Default constructor that builds a stack with a conventional default capacity (for example, 100).
  2. Capacity + initial contents constructor where the second argument seeds the stack with an initial sequence (for example, "ABCD").

Modernizing ch_stack constructors

For learning purposes, building ch_stack is great. For production code, prefer std::stack<T> (container adaptor) or std::vector<T> when you want direct access to the underlying storage. Still, if you’re implementing ch_stack, modern C++ makes constructor design safer and simpler:

Example: three constructors using the Rule of Zero

The following example shows a modern constructor set (default capacity, explicit capacity, and capacity + initial contents). Notice how the storage is managed automatically, and the constructors express intent through initialization lists.


#include <algorithm>
#include <cstddef>
#include <string_view>
#include <vector>

class ch_stack {
public:
    // 1) Default constructor (conventional default capacity)
    ch_stack() : ch_stack(100) {}

    // 2) Capacity constructor
    explicit ch_stack(std::size_t capacity)
        : max_len_(capacity ? capacity : 100),
          s_(max_len_),
          top_(0) {}

    // 3) Capacity + initial contents (seed the stack)
    ch_stack(std::size_t capacity, std::string_view init)
        : ch_stack(capacity)
    {
        const std::size_t n = std::min(init.size(), max_len_);
        std::copy_n(init.begin(), n, s_.begin());
        top_ = n; // current size (top index would be top_-1)
    }

    // (Push/pop omitted here; constructors are the focus.)

private:
    std::size_t max_len_;
    std::vector<char> s_;
    std::size_t top_; // number of valid elements currently in the stack
};

Key idea: max_len_ is capacity, and top_ is the current size. When top_ == 0, the stack is empty. When top_ == max_len_, the stack is full.

Which constructor runs? Read the call site

Now let’s map calling statements to specific constructors. These examples are intentionally short, because the selection rules are purely about argument lists.

ch_stack data;            // calls ch_stack()  ➜ delegates to ch_stack(100)
ch_stack w(4, "ABCD");    // calls ch_stack(std::size_t, std::string_view)

Arrays and “many stacks”

In legacy code you may see:

ch_stack d[N];

That creates N stack objects and calls the default constructor for each element. The important detail: [N] is an array declarator, not a function argument, so it does not affect overload resolution.

In modern C++, you’ll usually prefer one of these forms:


#include <array>
#include <vector>

std::array<ch_stack, N> fixed;   // when N is compile-time constant
std::vector<ch_stack> many(N);   // when N is runtime or just more flexible

Stack templates: same constructor idea, generic element type

A class template lets you reuse the same stack logic for different element types. The “constructor story” stays the same—overloads choose capacity, initialization, and behavior—but the element type becomes a parameter.

Below is a modern template version that demonstrates the same constructor theme while avoiding raw pointers and custom destructors. This is closer to “current API” C++: containers handle memory, and copy/move operations work automatically (Rule of Zero).

Figure 5-3: Stack class-template definition (modernized)
#ifndef STACK_H
#define STACK_H

#include <cstddef>
#include <vector>

template <typename T>
class Stack {
public:
    // default capacity is 10; validate capacity inline
    explicit Stack(std::size_t capacity = 10)
        : size_(capacity ? capacity : 10),
          top_(0),
          data_(size_) {}

    bool push(const T& value) {
        if (isFull()) return false;
        data_[top_++] = value;
        return true;
    }

    bool pop(T& out) {
        if (isEmpty()) return false;
        out = data_[--top_];
        return true;
    }

    bool isEmpty() const noexcept { return top_ == 0; }
    bool isFull()  const noexcept { return top_ == size_; }

private:
    std::size_t size_;   // capacity
    std::size_t top_;    // current size
    std::vector<T> data_;
};

#endif
Fig. 5-3 Stack Template (modern C++ using RAII and the Rule of Zero)

Note a practical constraint: constructing std::vector<T> data_(size_) default-constructs T elements, so T must be default-constructible for this exact implementation. If that’s not acceptable, you’d switch to a design that uses reserve + push_back (or stores std::optional<T> slots) depending on your requirements.

Takeaways


SEMrush Software