C ++ Klassenkopie (Zeigerkopie)

9

Wenn Sie eine Kopie einer Klasse erstellen, die eine Zeigervariable definiert, wird der Zeiger zwar kopiert, aber die Daten, auf die der Zeiger verweist, werden nicht kopiert.

Meine Frage ist: Soll man davon ausgehen, dass die "Zeigerkopie" in diesem Fall einfach einen neuen Zeiger (dynamische Speicherzuweisung) desselben Typs instanziiert? ZB ist der neue Zeiger einfach eine neue Zuweisung, die eine willkürliche Speicheradresse enthält, und man sollte darauf achten, diesen neuen Zeiger auf die entsprechende Speicheradresse zu richten?

Ich nehme an, dass es eine recht einfache Antwort auf diese Frage gibt, und ich entschuldige mich für seine triviale Natur, aber ich versuche, Hinweise auf einer tieferen Ebene zu verstehen, und dies kam auf meine Forschungshinweise im Internet.

Grüße,

Tschad

    
Chad Kemp 17.02.2011, 18:51
quelle

5 Antworten

14

Der Zeiger wird einfach als Wert kopiert - also beide Klassen zeigen auf den gleichen ursprünglichen Speicher, es findet keine neue Zuweisung statt. Flache Kopie - das ist die Standardsprache.

Wenn Sie neuen Speicher reservieren und eine Kopie der Daten erstellen müssen, müssen Sie dies selbst im Kopierkonstruktor tun. Deep copy - Sie müssen dies selbst tun

edit: Dies ist einer der Vorteile von C ++, Sie können frei entscheiden, wie das Kopieren funktioniert. Es kann sein, dass eine Kopie des Objekts, das nur Lesezugriff auf den Speicher hat, die Kosten des Kopierens des Speichers vermeiden kann. Sie können auch Klassen implementieren, die nur dann eine Kopie der Originaldaten erstellen, wenn das neue Objekt einen Schreibvorgang ausführen muss.

    
Martin Beckett 17.02.2011, 18:54
quelle
6

Zunächst ist der Zeiger in Ihrer Klasse statisch (d. h. der Compiler weiß, dass es in dieser Klasse einen Zeiger gibt und welche Größe er hat, sodass keine dynamische Speicherzuweisung benötigt wird, wenn die Klasse instanziiert wird).

Wenn Sie die Klasse kopieren (und keinen speziellen Kopierkonstruktor definiert haben), zeigt der Zeiger in der neuen Klasse auf dieselbe Stelle im Speicher wie der Zeiger in der alten Klasse. Um zu klären:

%Vor%

Wenn Sie nun beim Kopieren neuen Speicher zuweisen wollen, müssen Sie einen Kopierkonstruktor und einen Kopierzuweisungskonstruktor schreiben:

%Vor%

Wenn Sie dies tun, sollten Sie auch einen Destruktor schreiben (siehe Dreierregel ) ), da der Speicher, der in den Kopier- / Kopierzuweisungskonstruktoren zugewiesen wird, aufgehoben werden muss, wenn die Klasse zerstört wird:

    
Paul 17.02.2011 18:58
quelle
3

Zeiger instanziieren die dynamische Speicherzuweisung nicht. Zeiger und Zuweisungen sind ganz andere Dinge.

Wenn Sie einen Zeiger kopieren, der auf dynamisch zugewiesenen Speicher verweist, haben Sie zwei Zeiger, die auf denselben zugewiesenen Speicher zeigen. Da Sie es kopiert haben, zeigt es bereits auf den Speicherblock. Wenn der kompiliergenerierte Kopierkonstruktor verwendet wird, verweist der neue Zeiger genau auf das gleiche wie den alten Zeiger. Sie müssen nichts damit machen, wenn das in Ordnung ist.

Sie haben das Problem, wann Sie den Speicher freigeben müssen. Wenn Sie es zweimal freigeben, führt dies in der Regel zu einer Beschädigung des Heaps, was unangenehm ist. Wenn Sie es nicht freigeben, wird ein Speicherverlust verursacht, der unter Umständen akzeptabel ist. Es zu befreien, bevor der andere Zeiger durch es geht, wird auch Probleme verursachen. Aus diesem Grund gehen Leute, die mehrere Zeiger auf den gleichen Speicher haben, oft zum Boost-Projekt und verwenden ihre shared_ptr-Vorlage (die im kommenden neuen Standard enthalten sein wird und in den meisten aktuellen Systemen vorhanden ist).

>

Wenn Sie möchten, dass jeder Zeiger auf einzelne Speicherbereiche zeigt, müssen Sie dies einrichten, indem Sie einen eigenen Kopierkonstruktor erstellen, einen neuen Block zuweisen und die erforderlichen Daten darin kopieren. (Sie müssen aus genau den gleichen Gründen auch einen eigenen Zuweisungsoperator und einen eigenen Destruktor schreiben, damit Sie den Speicher freigeben können. Es gibt eine Faustregel, die Regel der Drei, die besagt, dass Sie Ihre eigene Kopie schreiben müssen Konstruktor, Zuweisungsoperator oder Destruktor müssen Sie wahrscheinlich alle schreiben.)

    
David Thornley 17.02.2011 19:01
quelle
2

Der kopierte Zeiger zeigt auf die exakt gleiche Adresse. Es gibt keine neue Zuweisung.

    
Erik 17.02.2011 18:54
quelle
1

Ja, Zeiger enthalten einfach Speicheradressen. Wenn Sie eine tiefere Kopie erstellen möchten, müssen Sie dies im Kopierkonstruktor selbst programmieren.

Wenn Sie immer die gleiche Art von Daten über einen Zeiger aus derselben Klasse referenzieren und die Daten zusammen mit den Objekten kopieren müssen, könnten Sie auch überlegen, ob Sie nur ein einfaches Element und keinen Zeiger erstellen möchten.

    
Olli Etuaho 17.02.2011 18:57
quelle

Tags und Links