2010-02-26 7 views
2

Jetez un oeil sur le code suivant vous n'êtes pas obligé de lire le code entier suffit de lire le code du constructeur de copie et le programme principal.
la déclaration suivante dans le constructeur de copieproblème de copie superficielle!

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

cette déclaration devrait faire une copie superficielle en cas de tableau de pointeurs alors s'il vous plaît voir le code du constructeur de copie et la fonction principale je l'ai mentionné problêmes dans le 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"); 

} 
+2

okay; et quel est le problème? – Vlad

+1

s'il vous plaît indenter votre code c'est difficile à lire! –

Répondre

0

Vous obtenez exactement ce que vous avez écrit. Votre copie fait une copie du tableau. Vous ne devriez pas vous attendre à ce que les changements apportés au premier vecteur touchent le second.

Notez que vous avez supprimé des pointeurs sur les chaînes du premier vecteur. Dans la seconde, ils restent intacts.

+0

monsieur dans le constructeur de copie ptr est un pointeur vers le pointeur, il semble que l'instruction que j'ai mentionnée dans le constructeur de copie copie la valeur de pointeur de l'objet passé dans le pointeur de l'objet en cours de création. votre réponse me confond. –

+0

@Zia: le constructeur de copie copie les ** valeurs ** des pointeurs du premier vecteur vers le second. Par conséquent, lorsque les valeurs des pointeurs dans le premier vecteur sont modifiées via appel à 'makeEmpty', les valeurs dans le second vecteur (qui sont les copies des valeurs d'origine) restent les mêmes. – Vlad

+0

ya vous êtes maintenant j'ai compris le point merci beaucoup –

0

Pour une copie peu profonde, il suffit de faire:

ptr = object.ptr; 

dans le constructeur de copie.

La seule raison pour laquelle vous boucle par ptr comme vous l'avez fait, il est spécifiquement faire une copie en profondeur ...

EDIT:

Il faut comprendre que lorsque vous faites:

ptr=new t[size]; 

vous allouez un nouveau bloc de mémoire de taille "size * sizeof (t)" à ptr.

Et

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

Copie le contenu de object.ptr [i] pour PTR [currentsize].

Vous pouvez aussi simplement omettre l'appel à nouveau et changer cette ligne à:

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

encore confus, sir ptr [currentsize ++] est un pointeur et l'objet.ptr [i] est également un pointeur dans le constructeur de copie. Maintenant l'instruction ptr [currentsize ++] = object.ptr [i] signifie que l'adresse contenue dans le object.ptr [i] sera assigné à ptr [currentsize ++] maintenant si nous changeons l'objet qui est passé dans le constructeur de copie alors l'objet créé iterms de l'objet passé devrait être affecté. mais ce n'est pas si vous exécutez le code. –

+0

ptr [currentsize ++] et object.ptr [i] ne sont pas des pointeurs, ce sont des objets de type t. Même si t se trouve être un type de pointeur, cela n'a pas d'importance, car votre méthode display() imprime la * valeur * de ptr [i], qui, si un pointeur, serait une adresse. Envisagez-vous de remplacer ptr [i] par * ptr [i] dans votre méthode d'affichage? – Jimmeh

1

La copie est w.r.t. peu profonde les données de chaîne réelles, mais pas la chaîne pointeurs. Les chaînes sont toujours présentes dans la mémoire; faire quoi que ce soit aux pointeurs dans le premier objet ne changera pas les pointeurs dans le second.

Essayez de changer ptr[i]=null dans la fonction de votre makeEmpty() dans strcpy(ptr[i], "a") et vous devriez les voir se changer en object2 aussi (ainsi que dans le char *array[] original).

Si vous voulez une copie réelle peu profonde qui fonctionne comme vous le souhaitez, utilisez simplement ptr = object.ptr.

+2

@tzman - Il est vrai que vous savez que le type de template est un char * dans son exemple, mais c'est un template et donc vous ne pouvez pas vous attendre à utiliser strcpy sur d'autres types. –

+0

C'est vrai, bien sûr. C'était juste une tentative de démontrer que la copie était en effet peu profonde en ce qui concerne les données de chaîne dans son code d'exemple. – tzaman

2

Vous ne modifiez pas les pointeurs vers NULL dans l'objet 1, objet que vous attendez de ne voir aucun résultat lorsque vous appelez l'affichage. Puisque object1 a toujours des adresses valides contenues dans celui-ci, vous allez bien sûr toujours voir les résultats car le tableau de type t n'a pas été détruit/désalloué. Si dans makeEmpty() vous détruisiez/détruisiez les objets, vous obtiendriez un comportement indéfini (probablement un SEGFAULT) lorsque vous appelez object1.afficher(); comme les pointeurs, bien qu'ils aient encore des adresses contenues en eux, ne sont pas valides car ils pointent vers la mémoire détruite.

0

Ne pas incrémenter currentsize

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

Pour comprendre ce qui est copié, modifiez votre fonction d'affichage à ceci:

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

Cela montrera non seulement le contenu du pointeur (en chaîne), mais montre où le pointeur est stocké.

Vous devez ensuite modifier votre programme pour faire également object.display(). Vous verrez alors qu'il y a deux copies du pointeur. Lorsque vous utilisez makeEmpty() pour mettre à zéro les pointeurs, vous modifiez uniquement une copie du pointeur.

Questions connexes