1

I was building a small template stack class for a side project and it appeared to be working correctly. However, when I tried it with strings it doesn't appear to work. I have no compilation errors or warnings. I simply get no output. I'm a little rusty in C++ but I wasn't expecting to get blocked by a problem that seems this simple.

Example of some output

My main function (for testing):

#include <iostream>
#include <fstream>
#include <string>
#include "myStack.h"

int main()
{

    bool repeat = true;
    int option = -1;

    std::cout << "Option (1 - String | 2 - Integer) : ";
    std::cin >> option;
    std::cout << "\n";

    switch (option)
    {

    case 1:
    {
        myStack<std::string> stringStack;
        stringStack.push("!");
        stringStack.push("there");
        stringStack.push("Hello");
        stringStack.show();
        break;
    }

    case 2:
    {
        myStack<int> intStack;
        intStack.push(3);
        intStack.push(2);
        intStack.push(1);
        intStack.show();
        break;
    }

    default:
        break;
    }

    std::cout << "\n";

    return 0;
}

Relevant parts of my stack class:

#pragma once

template <typename T>
class myStack
{

  private:
    T *elements;
    size_t capacity;

  public:
    myStack();
    T top();
    size_t size();
    void push(T pushed);
    void pop();
    bool isEmpty();
    void show(std::ostream &out = std::cout);
};

template <typename T>
myStack<T>::myStack()
{
    this->elements = NULL;
    this->capacity = 0;
}


template <typename T>
void myStack<T>::push(T pushed)
{
    this->elements = (T *)realloc(this->elements, (this->capacity + 1) * sizeof(T));
    this->elements[this->capacity] = pushed;
    this->capacity++;
}

template<typename T>
void myStack<T>::show(std::ostream &out)
{
    for (int i = this->capacity - 1; i >= 0; i--)
    {
        out << this->elements[i] << std::endl;
    }
}
8
  • 1
    By the way, you seem to be missing warnings when actually compiling the source files. The warnings are present only for the linking. Commented Apr 7, 2019 at 5:50
  • 1
    You can't store std::string that way. It is not trivially copyable. Commented Apr 7, 2019 at 5:54
  • 2
    GCC actually does give a relevant warning here. Commented Apr 7, 2019 at 5:55
  • 2
    Allocating memory for a std::string using realloc() (or malloc(), or calloc()) gives undefined behaviour. If you must dynamically allocated a std::string, or a set of them, use operator new. It works with C++ class types that have constructors, including std::string. Commented Apr 7, 2019 at 6:00
  • 1
    Oh alright! I was used to malloc() and realloc() and just expected it to work here too. Thanks for the help everyone! Commented Apr 7, 2019 at 6:03

1 Answer 1

3

Use of

this->elements = (T *)realloc(this->elements, (this->capacity + 1) * sizeof(T));
this->elements[this->capacity] = pushed;

to manage an array of std::strings is not right. Use of realloc to allocate memory is ok. However, it does not initialize the object properly. The second line is cause for undefined behavior since the object was not initialized properly.

If you are allowed to use std::vector, use it.

template <typename T>
class myStack
{

  private:
    std::vector<T> elements;

  ...
};

Then, use of capacity can be replaced by elements.size().

push can be simplified to:

template <typename T>
void myStack<T>::push(T pushed)
{
    this->elements.push_back(pushed);
}

You'll have to update show() accordingly too.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.