tags:

views:

97

answers:

6

Have a look at the following code you are not required to read the whole code just read the code of copy constructor and the main program.
the following statement in the copy constructor

//the statement below should do the shallow copy 
    ptr[currentsize++]=object.ptr[i];

this statement should do a shallow copy in case of array of pointers so please see the code of copy constructor and the main function i have mentioned the problemes in the code.

#include<iostream.h>
template<typename t>
class vector
{
public:
    vector(int size);
    vector(const vector<t>&);
    void insert(t);
    void display()const;
    void makeEmpty();//sets all pointers to NULL
private:
    t* ptr;
    int size;
    int currentsize;
};
template<typename t>
vector<t>::vector<t>(int s)
{
    currentsize=0;
    size=s;
    ptr=new t[size];
}
//copy constructor
template<typename t>
vector<t>::vector<t>(const vector<t>& object)
{
    size=object.size;
    ptr=new t[size];
    currentsize=0;
    for(int i=0;i<object.currentsize;i++)
    {
        //the statement below should do the shallow copy 
        ptr[currentsize++]=object.ptr[i];
    }
}
template<class t>
void vector<t>::insert(t element)
{
    if(currentsize < size)
        ptr[currentsize++]=element;
}
template<class t>
void vector<t>::display()const
{
    for(int i=0;i<currentsize; i++)
    {
        cout<<ptr[i]<<endl;
    }
}
template<class t>
void vector<t>::makeEmpty()
{
    for(int i=0;i<currentsize;i++)
        ptr[i]=NULL;
}
main()
{
    vector<char*>object(10);
    char *array[]={"zia","arshad","muneeb"};
    object.insert(array[0]);
    object.insert(array[1]);
    object.insert(array[2]);
    vector<char*> object1=object;
    cout<<"displaying the new object"<<endl;
    object1.display();
    object.makeEmpty();//sets all pointers to NULL
    //now here the object 1 should be changed but its not 
    cout<<"again displaying object1"<<endl;
    object1.display();//still displaying the three names 

    cout<<endl;
    system("pause");

}
A: 

You get exactly what you wrote. Your copying makes a copy of the array. You shouldn't expect changes to the first vector touch the second one.

Note that you've removed pointers to the strings in the first vector. In the second they stay intact.

Vlad
sir in copy constructor ptr is a pointer to pointer , it seems that the statement i mentioned in the copy constructor copies the poiner value of the passed object in the pointer of object being created. your answer is confusing me .
Zia ur Rahman
@Zia: the copy constructor copies **values** of pointers from the first vector to the second. Therefore, when the values of the pointers in the first vector are change via call to `makeEmpty`, the values in the second vector (which are the copies of original values) stay the same.
Vlad
ya you are right now i have understood the point thank you very much
Zia ur Rahman
You are welcome!
Vlad
A: 

For a shallow copy, just do:

ptr = object.ptr;

in the copy constructor.

The only reason you would loop through ptr like you've done there is specifically to do a deep copy...

EDIT:

Understand that when you do:

ptr=new t[size];

you're allocating a new memory block of size "size*sizeof(t)" to ptr.

And

ptr[currentsize++]=object.ptr[i];

Copies the contents of object.ptr[i] to ptr[currentsize].

You could also just omit the call to new and change that line to:

&ptr[currentsize++]=&object.ptr[i];
Jimmeh
still confusing , sir ptr[currentsize++] is a pointer and the object.ptr[i] is also a pointer in the copy constructor.now the statement ptr[currentsize++]=object.ptr[i] means that the address contained in the object.ptr[i] will be assigned to ptr[currentsize++] now if we chang the object that is passed in the copy contructor then the object created iterms of passed object should be affected. but its not if you run the code.
Zia ur Rahman
ptr[currentsize++] and object.ptr[i] are not pointers, they are objects of type t.Even if t happens to be a pointer type, this doesn't matter, because your display() method is printing the *value* of ptr[i], which, if a pointer, would be an address.Consider changing ptr[i] to *ptr[i] in your display method?
Jimmeh
+1  A: 

The copy is shallow w.r.t. the actual string data, but not the string pointers. The strings are still present in memory; doing anything to the pointers in the first object won't change the pointers in the second one.

Try changing ptr[i]=null in the your makeEmpty() function into strcpy(ptr[i], "a") and you should see them get changed in object2 too (as well as in the original char *array[]).

If you want an actual shallow copy that works like you want, just use ptr = object.ptr.

tzaman
@tzman - It's true you know the template type is a char * in his example, but it is a template and thus you can't expect to use strcpy on other types.
RC
True, of course. It was just an attempt to demonstrate that the copying was indeed shallow with regards to the string data in his example code.
tzaman
+2  A: 

You aren't changing the pointers to NULL in object1 which is the object you are expecting to see no results from when you call display. Since object1 still has valid addresses contained within it, you're of course going to still see the results as the array of type t hasn't been destroyed/deallocated.

If in makeEmpty() you were destroying/destructing the objects, then you would get undefined behavior (probably a SEGFAULT) when you call object1.display(); as the pointers, though they still have addresses contained within them, are invalid as they point to destroyed memory.

RC
A: 

Don't increment currentsize

//ptr[currentsize++]=object.ptr[i];
ptr[i]=object.ptr[i];
Winder
+2  A: 

To understand what is being copied, modify your display function to this:

template<class t>
void vector<t>::display()const
{
    for(int i=0;i<currentsize; i++)
    {
        cout<<(void* )&ptr[i] << ": " << ptr[i]<<endl;
    }
}

This will not only show the contents of the pointer (as a string), but show where the pointer is being stored.

You should then modify your program to also do a object.display(). You will then see that there are two copies of the pointer. When you use makeEmpty() to zero out the pointers, you are only modifying one copy of the pointer.

R Samuel Klatchko