Reputation: 11
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
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:
Stack
object by referenceconst 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