2012-08-23 15 views
5

Ein Kopierkonstruktor wird für viele Dinge verwendet, z. B. wenn ich Zeiger verwenden oder dynamisch Speicher für ein Objekt zuweisen muss. Aber ein Blick auf dieses Beispiel bei tutorialpoint.com:Beispiel eines Kopierkonstruktors erläutern

#include <iostream> 

using namespace std; 

class Line 
{ 
public: 
    int getLength(void); 
    Line(int len);    // simple constructor 
    Line(const Line &obj); // copy constructor 
    ~Line();      // destructor 

private: 
    int *ptr; 
}; 

// Member functions definitions including constructor 
Line::Line(int len) 
{ 
cout << "Normal constructor allocating ptr" << endl; 
// allocate memory for the pointer; 
ptr = new int; 
*ptr = len; 
} 

Line::Line(const Line &obj) 
{ 
cout << "Copy constructor allocating ptr." << endl; 
ptr = new int; 
*ptr = *obj.ptr; // copy the value 
} 

Line::~Line(void) 
{ 
cout << "Freeing memory!" << endl; 
delete ptr; 
} 
int Line::getLength(void) 
{ 
return *ptr; 
} 

void display(Line obj) 
{ 
    cout << "Length of line : " << obj.getLength() <<endl; 
} 

// Main function for the program 
int main() 
{ 
    Line line(10); 

    display(line); 

    return 0; 
} 

das Ergebnis:

Normal constructor allocating ptr 
Copy constructor allocating ptr. 
Length of line : 10 
Freeing memory! 
Freeing memory! 

und wenn ich auf Kommentar (den Kopierkonstruktor) und den Code innerhalb destructor habe ich die gleichen Ergebnisse:

Normal constructor allocating ptr 
Length of line : 10 

Was ist der Unterschied zwischen der Verwendung des Kopierkonstruktors hier oder nicht? Auch warum "Free Memory!" zweimal vorkommen?

+2

Schauen Sie sich die Ergebnisse an. Im ersten Beispiel ordnen Sie zwei verschiedene Ints zu und geben beide frei. In der zweiten vergeben Sie eine und geben sie zweimal frei. Nicht gut. – chris

+0

es ist nicht im zweiten Beispiel freigegeben, ich habe nur vergessen, den "cout <<" Kommentar Speicher freizugeben!"Anweisung innerhalb des Konstruktors, also ist es tatsächlich nicht freigegeben – Omar

+0

Dann haben Sie etwas zugewiesen, das Sie nicht befreit haben, das ein Speicherverlust ist, wenn es anfängt, komplexer zu werden als nur das Erstellen und Beenden des Programms. – chris

Antwort

3

Das Argument zur display()-Funktion wird als Wert übergeben, daher ruft der Compiler den Kopierkonstruktor auf, um es zu erstellen. Wenn die Klasse ihren Kopierkonstruktor definiert, erhält man die korrekte Semantik: Der Kopierkonstruktor erstellt eine Kopie, und diese Kopie hat ihren eigenen Speicher, um die Länge zu halten. Wenn Sie den Kopierkonstruktor entfernen, generiert der Compiler einen für Sie, und die Kopie, die an display() übergeben wird, hat den gleichen Zeiger wie das Original. Wenn diese Kopie zerstört wird, löscht sie den Speicher, auf den ptr zeigt. Wenn das Original zerstört wird, löscht es den gleichen Speicher erneut (was hier keine sichtbaren Auswirkungen hat). Das ist definitiv nicht das, was Sie wollen, weshalb Sie einen Kopierkonstruktor definieren müssen. Wie @Joe sagt: Im Destruktor, drucke den Wert von `ptr ', um dies deutlicher zu sehen.

4

Die Adresse des freizugebenden Speichers ausgeben.

Ich glaube, Sie werden feststellen, dass der Compiler den Konstruktor für Sie generiert, hat eine Wertkopie des Inhalts, einschließlich des Zeigers, und Sie sind doppelt frei den Zeiger und nur Glück, dass die Laufzeit nicht darüber klagt .

Der vom Compiler generierte Kopierkonstruktor wird immer noch aufgerufen - nichts hat sich in dieser Hinsicht geändert, Sie drucken nichts davon, weil Sie es nicht geschrieben haben.

0

Ein Konstruktor eines Typs T der Form

T (const & T); 

Das einzige Argument eine konstante Referenz auf ein vorhandenes Objekt der gleichen Art sein muss Erstellt ein Duplikat des vorhandenen Objekts Verwendet, wenn eine Kopie eines Objekt wird benötigt Einschließlich Argumente für Funktionen, Ergebnisse von Funktionen zurückgegeben Probleme mit zeigerbasierten Arrays in C++: - Keine Bereichsüberprüfung. Kann nicht sinnvoll mit == verglichen werden. Keine Array-Zuweisung (Array-Namen sind Const-Pointer). Wenn das Array an eine Funktion übergeben wurde, muss die Größe als separates Argument übergeben werden.

1

Wenn wir unseren eigenen Kopierkonstruktor nicht definieren, erstellt der C++ - Compiler für jede Klasse einen Standardkopiekonstruktor, der eine elementweise Kopie zwischen Objekten ausführt. Der im Compiler erstellte Kopierkonstruktor funktioniert im Allgemeinen gut. Wir müssen unseren eigenen Kopierkonstruktor nur dann definieren, wenn ein Objekt Zeiger oder eine Laufzeitzuordnung von Ressourcen wie Dateikennung, eine Netzwerkverbindung hat.

Verwandte Themen