B-Mac
B-Mac

Reputation: 11

What happens in each scenario and how is this accomplished?

I have a Stack class defined. Now, I want to reverse the stack by passing it to a reverseStack function. I want to know what happens in various scenarios. And finally, what is the best way to do it.

STACK IMPLEMENTATION:

class Stack {
        public:
            Stack() {
                a = new int[25];
                capacity = 25;
            }
            Stack(int size) {
                a = new int[size];
                capacity = size;
            }
            ~Stack() {
                delete[] a;
            }
            void push(int x) {
                if (index == capacity - 1) {
                    cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
                    return;
                }
                a[++index] = x;
            }
            int pop() {
                if (index == -1) {
                    cout << "\n\nNo elements to pop\n\n";
                    return -1;
                }
                return a[index--];
            }

            int top();
            bool isEmpty();
            void flush();

        private:
            int capacity ;
            int* a;
            int index = -1; // Index of the top most element
    };

SCENARIO-1:

void reverseStack(Stack& s) {
    Stack s2;
    while (!s.isEmpty()) {
        s2.push(s.pop());
    }
    s = s2;
}

int main() {
    Stack s;
    s.push(1);
    s.push(2);
    s.push(3);
    reverseStack(s);
    return 0;
}

SCENARIO-2:

Stack reverseStack(Stack& s) {
    Stack s2;
    while (!s.isEmpty()) {
        s2.push(s.pop());
    }
    return s2;
}

int main() {
    Stack s;
    s.push(1);
    s.push(2);
    s.push(3);
    s = reverseStack(s);
    return 0;
}

In Scenario-1 (which fails), what does s = s2 inside the function mean? I think it's a member-wise copy. Would it have worked if the data members didn't involve a pointer (int* a)?

Scenario-2 fails as well for the same reason. How do I accomplish what I'm trying to?

Should I have a copy-constructor (and how do I implement it?). How about overloading the assignment operator (again, how do I implement?) ?

I tried to implement it this way:

Stack Stack::operator = (Stack s) {
    capacity = s.capacity;
    int* a = new int[capacity];
    for (int i = 0; i < capacity; i++) {
        a[i] = s.a[i];
    }
    index = s.index;
    return *this;
}

Upvotes: 1

Views: 66

Answers (1)

ichramm
ichramm

Reputation: 6642

About the scenarios, the best one is the second because of the return value optimization, i.e: The compiler will probably optimize away the copy of the return value and prevent an unnecessary copy.

Now, you are using dynamic memory in your class, which means the default implementation of the copy constructor and assignment operator will not work for you.

Copy constructor, it's almost the same as the assignment operator you write

Stack::Stack(const Stack& s)
 : capacity(s.capacity)
 , a(new int[capacity])
 , index(s.index)
{ // std::copy is just a shortcut, what you're doing is fine too
    std::copy(s.a, s.a + capacity, a);
}

The assignment operator you wrote is wrong in two ways:

  1. It should return a Stack object by reference
  2. The parameter should be a const reference

The rest is just ok

Stack& Stack::operator = (const Stack& s) {
    capacity = s.capacity;
    a = new int[capacity];
    for (int i = 0; i < capacity; i++) { // or std::copy
        a[i] = s.a[i];
    }
    index = s.index;
    return *this;
}

Update

Tentative implementation of the reverseStack function (without side-effects), assuming index contains the actual number of items in the stack

Stack reverseStack(const Stack& s) {
    Stack s2(s.capacity);
    for (int i = 0; i < s2.index; ++i) {
        s2.a[i] = s2.a[s2.index -i];
    }
    return s2;
}

Update Thanks to user657267 from pointing out int* a = new int[capacity]; was wrong

Upvotes: 1

Related Questions