2016-08-05 6 views
0

Viele Male haben wir Objekte von einigen Klassen müssen in Schleifen initialisiert werden betrieben werden bei:Leistungsverbesserung mit lokalen Objekten

Angenommen, ich habe eine Klasse/Struktur:

class employee 
{ 
    //member variables 
    //member methods - getter/setters,etc 
} 

Nehmen wir nun an möchte ich arbeiten Sie mit jedem Mitarbeiter in einem Array.

Ansatz 1:

for (loop on array of 10 employees) 
{ 
    employee emp(loop element); //using constructor of employee for initialization 
    //operate on the current loop element using emp 
} 

So wie pro mein Verständnis wird 10 emp Objekte, bis die Schleife finishes.Now da dies beinhaltet keine dynamische Speicherzuweisung erstellt bekommen, sobald die Steuerung geht aus Schleife , werden alle 10 Objekte gelöscht (& Speicher belegt mit 10 wird freigegeben) oder nur das letzte Objekt wird gelöscht (& Speicher belegt mit 9 Objekten wird nicht freigegeben).

Ansatz 2:

for (loop on array of 10 employees) 
{ 
    employee *emp=new employee(loop element); //using constructor of employee for initialization 
    //operate on the current loop element using emp 
    delete emp; 
    emp = nullptr; 
} 

Hier in Programmierer Steuerung ist so können wir die Erinnerung sich in jeder Iteration der Schleife befreien. Obwohl dies auch häufige Zuweisung & Freigabe von Heap-Speicher & verursachen kann einige Verschlechterung im Falle der Schleife ist für eine große Anzahl von Mitarbeitern.

Bitte helfen Sie mir bei der Abfrage in Approach 1 & Bitte schlagen Sie vor, welche der oben genannten Ansätze ist gut und wenn es einen besseren Ansatz für die gleiche?

Antwort

0

Ansatz 1 wird Mitarbeiterobjekt auf dem Stapel zuordnen, was sicherlich schneller ist als die Verwendung des dynamischen Speicherzuordners (Heap). Bei jeder Iteration wird das Mitarbeiterobjekt nicht mehr angezeigt, so dass sein Deskriptor jedes Mal aufgerufen wird. Das ist die gute Sache mit dem Stapel, es ist automatisch "Müll gesammelt", wenn Sie den Anwendungsbereich verlassen (siehe Is a destructor called when an object goes out of scope?).

1

Ansatz 1 ist besser, da Sie brauchen, um auf nicht verlassen new Balancing mit einem delete so ist es weniger wahrscheinlich, Speicher zu verlieren: Wenn Ihr Code „auf operate“ wurden 2 dann eine Ausnahme in Ansatz werfen delete würde nicht genannt werden. In Approach 1 würde der Destruktor aufgerufen werden, wenn eine Ausnahme ausgelöst wird, während der Stapel abwickelt.

Konzeptionell ja, in beide Ansätze, der Destruktor employee wird bei jeder separaten Iteration der Schleife aufgerufen werden. Das heißt, ein Compiler darf damit etwa als Optimierungsstrategie spielen wenn es keine Nebenwirkungen gibt.

1

Ich bin mir nicht sicher, ob ich das Problem verstehe. Wenn ich eine Schleife über Objekte habe und ich das Objekt nicht verändern möchte, würde ich sie nicht kopieren. Ich würde nur eine const Referenz verwenden.

for(auto const& e: employees) { 
    // operate on e 
} 

Wenn das Objekt geändert wird, dh nicht konstante Elementfunktion aufgerufen werden, würde ich eine nicht konstante Referenz verwendet

for(auto&& e: employees) { 
    // operate on e 
} 

In Ihrem Beispiel das „vorübergehende“ Mitarbeiter Objekt entweder Stapel - oder Heap-allokiert. Im ersten Fall wird das Objekt auf dem Stapel erstellt. Dies bedeutet, dass der Compiler den Stapelzeiger einfach auf einen Wert erhöht (oder verringert), der ausreicht, um auf dem Stapel Platz für ein Mitarbeiterobjekt zu haben, und dann den Konstruktor verwendet, um ihn zu initialisieren. Es wird keine Heap-Zuweisung durchgeführt, und es gibt nur ein Objekt vom Typ Mitarbeiter am Leben, plus dasjenige aus der Schleife. Die Lebensdauer endet, wenn der Bereich endet. In keinem Fall werden am Ende der Schleife zehn Objekte vorhanden sein.

Der zweite Fall ist identisch wr.t Lebensdauer, aber Objekte auf dem Haufen zugeordnet. Dies ist viel langsamer, aber wenn Sie die Objekte die ganze Zeit löschen, ist die Lebensdauer identisch. Ich würde empfehlen, in diesem Fall std::unique_ptr zu verwenden, da es auch ausnahmesicher ist und Ihnen die manuelle Speicherverwaltung erspart. Ihr Code hat einen Speicherverlust, wenn der Operationsteil eine Ausnahme auslöst.

Verwandte Themen