2016-03-27 6 views
2

Ich habe ein Programm geschrieben, um die durchschnittliche Pfadlänge in meinem rot-schwarzen Baum zu berechnen. Ich habe etwas wirklich komisches gefunden. Der Code ist unten dargestellt:Warum zeigen lokale Variablen, die von Zeigern und Objekten erzeugt werden, unterschiedliche Ausgaben an?

while (dataSize<MaxSize) { 
      int i = 0; 
      double aveLengthArr[1000]; 
      while (i < 1000) { 
       RedBlackTree rbt; 
       int* array= generateRandomInput(dataSize); 
       for (int n= 0; n < dataSize; n++) { 
        rbt->insert(array[n]); 
       } 
       aveLengthArr[i]=rbt->getAvePathLength(); 
       i++; 
      } 
      double mean = calAverage(aveLengthArr); 
      double stdDeviation = calDeviation(aveLengthArr, mean); 
      dataSize++; 
     } 

Wenn ein bestimmte Zeile Code RedBlackTree rbt; verwendet wird, die durchschnittliche Länge ist immer noch das gleiche mit unterschiedlichem Eingang array (ich habe es schon ausgetestet). Aber wenn der Code zu RedBlackTree* rbt=new RedBlackTree; geändert wird, erhält es das richtige Ergebnis und die Länge variiert.

So bin ich wirklich verwirrt, weil rbt eine lokale Variable ist, oder? Jedes Mal, wenn das Programm in eine neue Schleife springt, sollte die rbt ein völlig neues Objekt sein. Selbst wenn es nicht aktualisiert wird, sollte die Länge zunehmen, ist es aber nicht. Nach dem Verwenden eines Zeigers ist es richtig.

Eine andere seltsame Sache ist, dass, wenn ich das Programm mit Code RedBlackTree rbt; in Window7 ausführen, das Ergebnis richtig ist. Bei Verwendung von Ubuntu zeigt es das obige Problem. Irgendeine Idee wird geschätzt. Es ist wirklich schwer für mich, es herauszufinden.

Die RedBlackTree ist rot schwarz Baum und ich schreibe es als selbstdefinierte class.Part der Klasse wird unten gezeigt:

class RedBlackTree { 
private: 
    Node* root; 
    int redNodeNum; 
    int totalPathLength; 
public: 
    RedBlackTree() { 
     redNodeNum = 0; 
     totalPathLength = 0; 
    } 
} 
+1

'RedBlackTree rbt; rbt-> insert (array [n]); '? Was ist denn hier los? Ist 'RedBlackTree' eine Art intelligenter Zeiger? –

+0

@Sergey Tachenov @Sergey Tachenov @Sergey Tachenov @Sergey Tachenov @HostileFork gibt mir eine gute Erklärung, aber ich möchte immer noch herausfinden, warum 'RedBlackTree * rbt = new RedBlackTree' funktioniert, ohne root zu initialisieren. –

Antwort

2

Sie initialisieren nicht root in Ihrem Konstruktor.

Jedes Mal, wenn das Programm in eine neue Schleife springt, sollte die rbt ein völlig neues Objekt sein.

Das Objekt ist konstruiert jedes Mal. Aber der Speicher ist wahrscheinlich an der gleichen Adresse jedes Mal durch die Schleife (das ist keine Garantie). Und da Sie root nicht initialisieren, sehen Sie ein undefiniertes Verhalten, das wiederum wahrscheinlich ist, den letzten Wert aus der Schleife behaltend ... aber empfindlich auf Bedingungen des Kompilierens, Debuggens, Optimierens sein würde ...

https://en.wikipedia.org/wiki/Undefined_behavior

Eine weitere seltsame Sache ist, dass, wenn ich das Programm mit Code RedBlackTree rbt laufen; In Window7 ist das Ergebnis richtig. Bei Verwendung von Ubuntu zeigt es das obige Problem.

Dies ist die Art der Sache, die mit undefiniertem Verhalten passiert.

rbt->insert(array[n])

Wie @SergeyTachenov bemerkt hat, wird dies wahrscheinlich nicht kompilieren, da Ihr RedBlackTree keinen Zeiger in dem gegebenen Code ist (so würde rbt.insert(array[n]) sein. Es ist wahrscheinlich ein Artefakt von euch etwas auf halbem Weg zwischen der Zeiger-basierten Version und dem nicht-Zeiger auf Basis eines zu kopieren.

Posting ein vollständiges und kohärentes Beispiel wichtig ist, so lesen Sie bitte über MCVE: Minimal, Complete, Verifiable Examples. der Code in Ihrer Frage soll im Idealfall zusammenstellen, wie sie ist in an online compiler und zeigen deutlich Ihr Problem.

+0

Aber es erklärt nicht, warum ich es in Zeiger ändere und es funktioniert. Und der in Window laufende Code bekommt die richtige Antwort. –

+0

@SHUYULYU Ja, es erklärt es - lies auf undefiniertes Verhalten nach. Sie müssen von der Illusion von "und es funktioniert" in C++ - Programmierung wegkommen, nur weil ein Programm scheint zu arbeiten * unter einigen Umständen der Kompilation und Ausführung * bedeutet nicht, dass es korrekt ist. Es kann beim Laufen auftauchen und Sie überraschen, wenn Sie die Regeln der Sprache gebrochen haben, sogar in den Fällen, in denen es scheint, teilweise oder die meiste Zeit zu arbeiten. – HostileFork

+0

Ich werde es jetzt und bald wieder testen. –

Verwandte Themen