C++ oder ++C?

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Onraku
Beiträge: 43
Registriert: Fr Sep 09, 2011 2:14 pm

C++ oder ++C?

Beitrag von Onraku » Mo Apr 14, 2014 10:51 pm

Edit by Xin: 3 Beiträge rauskopiert als aus Thema Grafik als Link einfügen
Xin hat geschrieben:

Code: Alles auswählen

void SayHello( int howOften )
{
  howOften = howOften > 5 ? 5 : howOften;

  while( howOften-- )
    printf( "Hello\n" );   }
}
Uhh, bei mir säh das so aus:

Code: Alles auswählen

...
  while( howOften ){
    printf( "Hello\n" );
    howOften--;
 }
Aber ich bin ein großer Fan von keinen Klammern, was ja bei dir mit nur einer Anweisung geht. Und howOften zum dekrementieren nicht nochmal laden zu müssen ist ja auch nett. Ich mache nie Gebrauch von (i++) != (++i). Heißt ja auch C++, und nicht ++C. Also erst C lernen und dann kann ich noch einen draufsetzten. Solche simplen Tricks wie hier im Schleifenparameter muss ich immer erst irgendwo anders sehen.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Prozeduren bringen Fehlermeldungen

Beitrag von Xin » Mo Apr 14, 2014 11:20 pm

Onraku hat geschrieben:Ich mache nie Gebrauch von (i++) != (++i). Heißt ja auch C++, und nicht ++C. Also erst C lernen und dann kann ich noch einen draufsetzten.
Nicht ganz... C++ ist erhöht C um eins, liefert am Ende aber nur C zurück.
++C wäre durchaus ein sinnvollerer Name gewesen, gerade wenn man komplexere Objekte inkrementiert benötigt man keine Kopie des Originals als Rückgabe.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Onraku
Beiträge: 43
Registriert: Fr Sep 09, 2011 2:14 pm

Re: Prozeduren bringen Fehlermeldungen

Beitrag von Onraku » Mo Apr 14, 2014 11:52 pm

Über den Satz musste ich erstmal nachdenken.
in Pseudo-Assembler hieße das:

Code: Alles auswählen

c laden                                                                  //in stack
c kopieren in ckopie
c irgendwohin zurückgeben und wieder löschen  //=push oder pop? oder sagt man das nur bei einem Stack als Datenstruktur?
ckopie+1
c=ckopie und ckopie löschen                                // stack wie vorher

anstatt

laden
+1
rückgabe und löschen      //deutlich kürzer
Kannst du mir ein Beispiel für komplexes Objekt nennen, welches man einfach um ein erhöht?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

C++ oder ++C?

Beitrag von Xin » Di Apr 15, 2014 10:05 am

Onraku hat geschrieben:Über den Satz musste ich erstmal nachdenken.
in Pseudo-Assembler hieße das:

Code: Alles auswählen

c laden                                                                  //in stack
c kopieren in ckopie
c irgendwohin zurückgeben und wieder löschen  //=push oder pop? oder sagt man das nur bei einem Stack als Datenstruktur?
ckopie+1
c=ckopie und ckopie löschen                                // stack wie vorher
Step by Step... nehmen wir an, c wäre int, dann ist c synonym für Adresse, wo der Inhalt von c steht. c ist ein vom Stackpointer abhängiger Index. Der Wert C liegt auf dem Stack - und zwar um den Index c vom Stackpointer versetzt. Dann bedeutet ++c in Pseudoasm:

Code: Alles auswählen

Stackpointer + c_index addieren  // hier ist die Adresse des Inhaltes von C
Dereferenzieren und in CPU Register laden
Inhalt CPU Register um 1 erhöhen.
Inhalt CPU Register an Rückgabeadresse schreiben
Inhalt CPU Register an dereferenzierte Adresse zurückschreiben
Während c++ bedeutet:

Code: Alles auswählen

Stackpointer + c_index addieren  // hier ist die Adresse des Inhaltes von C
Dereferenzieren und in CPU Register laden
Inhalt CPU Register an Rückgabeadresse schreiben                      // <- vertauscht
Inhalt CPU Register um 1 erhöhen.                                              // <- vertauscht
Inhalt CPU Register an dereferenzierte Adresse zurückschreiben
Das funktioniert mit einem Int, das passt nämlich in ein CPU-Register. Deswegen gibt es bei primitiven Datentypen auch keine Geschwindigkeitseinbußen.
Onraku hat geschrieben:Kannst du mir ein Beispiel für komplexes Objekt nennen, welches man einfach um ein erhöht?
Konstruieren wir nun einen Text, der aus 2000 Zeilen besteht und implementieren nun beide ++ Operatoren so, dass sie dem Text eine 2001. Zeile hinzufügen. Dann sieht ++text etwa so aus:

Code: Alles auswählen

Text & Text::operator ++()
{
  this->Lines.append( "" );
  return *this;
}
Easy. Aber text++ ist so definiert, dass das zuvor gültige Ergebnis zurück geliefert werden muss:

Code: Alles auswählen

Text Text::operator ++(int)      // (!) keine Referenz als Rückgabe
{
  Text that( *this );  // <- hier werden alle 2000 Zeilen kopiert und für that eine neue Liste zusammengestellt. Das ganze muss also zwischengespeichert werden
  this->Lines.append( "" );
  return that;          // <- hier wird that nochmals an die Rückgabeadresse kopiert, also nochmal alle 2000 Zeilen kopieren, weil man ja keine Referenz zurückgeben kann!
}         // hier wird that zerstört, also 2000 Zeilen wieder zerstören
Der Aufruf 'text++;' führt also zu 4000 kopierten Zeilen und wenn man das Ergebnis - den unveränderten am Ende gar nicht verwendet, ist das viel Arbeit, um nichts zu erreichen.
Zum einen erkennen Compiler solche Konstrukte heute meistens, sie konstruieren that also direkt an der Rückgabeadresse. Um hier sicherzustellen, dass man die Arbeit nicht doppelt macht, kann man sich seit C++11 die Move-Semantik benutzen. Das garantiert, dass nur 2000 Zeilen kopiert werden. Aber es muss eben ein komplett neuer Text zurückgegeben werden, also auch erzeugt werden - was bei ++text nicht der Fall ist, denn da wird einfach der veränderte Text zurückgegeben.

Man sollte C++ also tunlichst nicht verwenden, besser ist ++C.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten