0

The following is a class template that implements a stack using an array:

#include <iostream>
using namespace std;

template <typename T>

class stack {

public:

    stack (int priv_size) {
        T a[priv_size];
        top = 0;
    }

    stack (const stack &s) {
        T b[priv_size];
        for (top=0; top<s.priv_size; top++) {
            b[top] = s.a[top];
        }
        top++;
    }

    ~stack () {}

    const stack& operator = (const stack &s) {
        T b[s.priv_size];
        for (top=0; top<s.priv_size; top++) {
            b[top] = s.a[top];
        }
        top++;
    }

    bool empty () {
        return top == 0;
    }

    void push (const T &x) {
        a[top++] = x;
    }

    T pop () {
        T c = a[--top];
        return c;
    }

    int size () {
        return priv_size;
    }

    friend ostream& operator << (ostream &out, const stack &s) {
        int i;
        out << "[";
        for (i=0; i<s.top-1; i++) {
            out << s.a[i] << ", ";
        }
        if (i == s.top-1) out << s.a[s.top-1];
        out << "]";
        return out;
    }

private:
    int priv_size;
    int top;
    T a[];
};

int main () {
    stack<int> s(10);

    cout << "stack s is empty: " << s << endl;

    s.push(42);
    s.push(17);

    cout << "stack s has 2 elements: " << s << endl;

    cout << "Removing " << s.pop() << " from the stack..." << endl;

    return 0;
}

However as i was trying out the different methods of the class in main I realized that although priv_size is initialized to the value of 10 here: stack<int> s(10); it loses its value right after the constuctor is called.

When i tried debugging in my IDE i realized that once the constructor stack (int priv_size) is called it created another variable priv_size that is initialized to the value of 10 instead of using the priv_size member of the class. The previous can also be seen here:

class member priv_size memory address (image)

and here:

unwanted variable priv_size memory address (image)

where the two variables are stored in different memory slots.

Why are the two variables different and why is the one in the second image created in the first place?

I have also tried implementing the class methods outside of the class, like this:

stack<T>::stack (int priv_size) {
    T a[priv_size];
    top = 0;
}

but i get these two error messages:

Member declaration not found

Type 'T' could not be resolved

What is going on here?

Thanks in advance.

PS: I am aware there are a couple very similar questions posted already, but the answers to those do not seem to fit my problem as my issue seems to be in the class itself and not in main or any other function. Here are two links to some similar questions: C++ Class members lose values assigned in a member function Losing a data member of a base class after the constructor is called

808kalli
  • 23
  • 7
  • 2
    You are not assigning anything to the `private priv_size` whereas [you should be](https://stackoverflow.com/q/6185020/11683). – GSerg Mar 05 '21 at 09:11
  • 3
    `T a[priv_size];` in constructor declare a new vairable, doesn't set member (and in a wrong way as VLA is a C++ extension). – Jarod42 Mar 05 '21 at 09:12
  • Please be careful that the name priv_size in the parameters of the constructor has nothing to do with the priv_size which is declared private in the class. These are two total different variables. You must assign priv_size in the constructor – RoQuOTriX Mar 05 '21 at 09:13
  • 2
    I'd recommend to get a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and start all over again. You are missing many basics about the language. You are also relying on compiler specific extensions that are not standard C++. If you are using g++ you should compile with -pedantic -Wall – Lukas-T Mar 05 '21 at 09:49
  • 1
    `T a[];` - um.. – WhozCraig Mar 05 '21 at 09:54
  • if you can you should use a `std::vector` rather than an array of unspecified size as member. I'm not even sure if that is legal and when its a compiler extension then you are already using fancy features, so why not `std::vector` – 463035818_is_not_an_ai Mar 05 '21 at 10:05

3 Answers3

1
stack (int priv_size) {
    T a[priv_size];
    top = 0;
}

Problem 1: Your constructor doesn't initialise the member a. It creates a local array.

Problem 2: The size of the array is not a compile time constant. The program is ill-formed.

Problem 3: You don't initialise the priv_size member either.

private:
    int priv_size;
    int top;
    T a[];

Problem 4: You didn't specify size of the array member a. The program is ill-formed.


although priv_size is initialized to the value of 10 here: stack s(10); it loses its value right after the constuctor is called.

Your assumption is wrong. The constructor doesn't set the value of priv_size member, so no value was lost.

where the two variables are stored in different memory slots.

As far as I can tell, one variable is the parameter of the constructor and the other is the member variable that you didn't initialise.

Type 'T' could not be resolved

What is going on here?

To define a template, you need to use the keyword template and specify the template parameters. Like this for example:

template <typename T>
stack<T>::stack (int priv_size) {
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • I didnt choose this as the answer to my question because it doesn't really help understand the source of the problem, instead it points out all the other mistakes in the code itself, which i didnt look too much into, so natuarally it has many mistakes. I'm just getting into object-oriented programming so my code is expected to have a lot a flaws. Thanks for your response. – 808kalli Mar 05 '21 at 13:07
  • @808kalli note that a [mcve] is expected to have not many flaws, instead it should demonstrate the one issue your question is about and not more. Its not the answers fault that there is lots to tell ;) – 463035818_is_not_an_ai Mar 05 '21 at 13:49
  • @largest_prime_is_463035818 i understand that but isnt it vital for a complete question to provide all the information the other person might need to answer it? – 808kalli Mar 05 '21 at 14:12
  • @808kalli we dont need to see the other problems when the question is about the initialisation of a member variable. Your words, just slightly rephrased ;) Its good practice to trim your code down to a mcve before posting, ie remove anything that you can remove while keeping the code complete enough to demonstrate the issue – 463035818_is_not_an_ai Mar 05 '21 at 14:17
0

There are multiple issues with your code. For instance, T a[priv_size]; requires that priv_size is a compile-time constant. And in stack (const stack &s) {T b[priv_size];, the local variable b goes out of scope when the copy ctor ends, while the member a remains uninitialized.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I didnt choose this as the answer to my question because it doesn't really answers it, instead it points out all the other mistakes in the code itself, which i didnt look too much into, so natuarally it has many mistakes. I'm just getting into object-oriented programming so my code is expected to have a lot a flaws. Thanks for your response. – 808kalli Mar 05 '21 at 13:06
0

Why are the two variables different and why is the one in the second image created in the first place?

Because you declared two different variables.

Its the same issue as in :

struct foo {
    int x;
    foo(int a) {
        int x = a;
    }
};

foos constructor declares a local variable named x which shadows the member x and the member x is not initialized. Same with an array:

 struct bar {
      int a[5];
      bar() {
         int a[5];
      }
 };

The member a and the a in the constructor are two distinct arrays.

This is only answering your question, but there are more problems in your code. When you need an array whose size is only known at runtime you should use std::vector.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • I chose this as the answer to my question because it actually answers it without pointing out all the other mistakes in the code itself, which i didnt look too much into, so natuarally it has many mistakes. I'm just getting into object-oriented programming so my code is expected to have a lot a flaws. Thanks for your response. – 808kalli Mar 05 '21 at 13:05
  • @808kalli well, there are some problems in your code and, frankly, it looks like you went too fast by doing too many steps at once. Manually managing memory is not trivial and templates are not trivial and you have issues with both. Though, I concentrated on only one thing for the answer – 463035818_is_not_an_ai Mar 05 '21 at 13:11
  • well you are absolutlely right, i just heard about templates yesterday for the first time, and to be honest im not sure what most of the mistakes people pointed out in this post really mean :/ – 808kalli Mar 05 '21 at 13:48