Amr Keleg
Amr Keleg

Reputation: 336

Why isn't the following class doing shallow copy for the array arr?

I am implementing the following class for a stack based on arrays of fixed size:

class Stack{
    private:
        int arr[1000];
        int size;
    public:
        Stack(){ size=0; }
        int top(){
            assert(size>0);
            return arr[0];
        }
        void push(int v){ assert(size<1000); arr[size++] = v; }
        void pop(){ assert(size>0); size--; }
        bool empty(){ return size==0; }
        bool is_equal(Stack s){
            Stack c = *this;
            while(!c.empty() && !s.empty()){
                if (c.top() != s.top())
                    return false;
                c.pop();
                s.pop();
            }
            return c.empty() && s.empty();
        }
};

According to my knowledge the first line of the is_equal method will create another object (c) but the arr attribute will point to the same data of the original object. Thus popping data from c will affect the original stack's arr.

Surprisingly, this isn't happening.

The address of stack c's arr is different than the address of the original stack's arr and the data is copied correctly as if I have overloaded the assignment operator.

Am I missing something?

Upvotes: 0

Views: 102

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 597166

According to my knowledge the first line of the is_equal method will create another object (c) but the arr attribute will point to the same data of the original object.

No, it will not. There is no such thing as making a shallow-copy of a fixed array. The elements of the array in this will be copied to the array in the new object c. Just as the elements of whatever Stack object you pass to is_equal() will be copied to the array in the s parameter since you are passing it by value.

If you really wanted to share the array, you would need to allocate the array dynamically using new[] or std::malloc() and then have Stack store a pointer to the array. Copying a pointer from one object to another would give you the shallow-copy semantics you are thinking of.

Thus popping data from c will affect the original stack's arr.

No, it won't, because c has its own array that is independent of the array in either s or this.

The address of stack c's arr is different than the address of the original stack's arr

Correct. Because they are separate arrays in memory.

the data is copied correctly as if I have overloaded the assignment operator.

Yes, because you did not implement your own copy constructor or copy assignment operator, so the compiler implicitly implemented them for you. The implicit implementation will copy the array elements from the source object's array to the destination object's array.

And BTW, your is_equal() can be implemented without having to make any copies at all:

class Stack {
    private:
        int arr[1000];
        int size;
    public:
        ...
        bool is_equal(const Stack &s) const {
            if (size != s.size)
                return false;
            for (int i = 0; i < size; ++i) {
                if (arr[i] != s.arr[i])
                    return false;
            }
            return true;
        }
        ...
};

Or simply:

#include <algorithm>

class Stack {
    private:
        int arr[1000];
        int size;
    public:
        ...
        bool is_equal(const Stack &s) const {
            // pre-C++14...
            return (size == s.size) && std::equal(arr, arr + size, s.arr);

            // C++14 and later...
            return std::equal(arr, arr + size, s.arr, s.arr + s.size);
        }
        ...
};

Upvotes: 0

Hatted Rooster
Hatted Rooster

Reputation: 36503

According to my knowledge the first line of the is_equal method will create another object (c) but the arr attribute will point to the same data of the original object. Thus popping data from c will affect the original stack's arr.

No, that's wrong. The Stack object will get copied and get its own storage. Copying an array means copying over all its elements to a different part in memory. c and *this are two different Stack objects with two different arrays.

Upvotes: 2

Related Questions