Pre- oder Post-Inkrementierung bei for-Schleifen?
-
hustbaer schrieb:
Leute, Newsflash: üblich ist i++!
Wer was anderes glaubt lebt in einer Traumwelt.Kann ich aus meiner Erfahrung nicht bestätigen. Im jüngeren Code hier bei uns in der Firma sieht man das Postinkrement eigentlich nur noch wenns wirklich so benötigt wird, also sehr selten. Dann hab ich gerade mal in Effective C++ 3rd ed. und C++ Templates the complete guide geblättert bis ich auf das erste Inkrement gestoßen bin. Bei Meyers war das erste, das ich sah, Item 29 "++imageChanges;" und im anderen wars auf Seite 37 "++numElems;", also auch beides Prefix.
Auch wenn in anderem code Prefix vielleicht nicht üblig ist, halte ich es schon für sinnvoll, das für sich selbst erstmal als Default zu nehmen und es so einfach üblich zu machen, weil es eigentlich nie schlechter sein sollte, dafür aber manchmal besser ist. Und bei Template-Kram weiß man ja eh nicht mehr, was man da gerade überhaupt erhöht.
-
Hacker schrieb:
Nicht um den heißen Brei herumreden. ++i ist, gerade bei größeren Klassen, performanter.
Das musst du mir erst mal durch Messungen beweisen. Und ich Wette mit dir, dass wenn du einen Fall findest bei dem das wirklich zutrifft, die Klasse noch ganz andere Probleme hat.
Gegenhypothese: es macht absolut 0 Unterschied, solange der Typ etwas so anspruchvolles wie ein iterator ist.
-
otze schrieb:
Hacker schrieb:
Nicht um den heißen Brei herumreden. ++i ist, gerade bei größeren Klassen, performanter.
Das musst du mir erst mal durch Messungen beweisen. Und ich Wette mit dir, dass wenn du einen Fall findest bei dem das wirklich zutrifft, die Klasse noch ganz andere Probleme hat.
Gegenhypothese: es macht absolut 0 Unterschied, solange der Typ etwas so anspruchvolles wie ein iterator ist.
Na, dann lügt Ethon schonmal. Oder du hast wahrscheinlich ein "nicht" vergessen.
-
Ich glaube, dass Ethon exakt so viel gemessen hat wie du.
-
otze schrieb:
Ich glaube, dass Ethon exakt so viel gemessen hat wie du.
Ich habe recht viele Iteratoren mit Shared Pointern darin.
Jedes Postfix-Inkrementieren würde von daher ein Ref-Plus und ein Ref-Minus bedeuten. Und da der Refcounter threadsicher manipuliert wird ist da schon etwas Overhead dabei.Ich könnte das messen, der restliche Overhead würde aber den Unterschied schlucken (denke ich mal). Aber hey, wieso die Taktzyklen wegwerfen wenn es sie gratis gibt. Man muss kein Zeichen mehr tippen, einfach nur Reihenfolge vertauschen.
-
*seufz* da sBringt und so nicht weiter.
Hier mal ein Argument.
Angenommen, unser Typ ist ein normaler, halbwegs sinnvoll implementierter Iterator.
Dann wird er in keinem Fall komplizierter sein als:
class iterator{ private: T* pointer1,....,pointerN; std::size_t pos1,....,posN; public: //ich benutze mal einfach namen, weil ich mir nie merken kann, wie die //pre/postincrement syntax ist inline iterator& preinc(); inline iterator postinc(); };
angenommen, preinc ist sehr komplex, dnan schauen wir uns die implementierung nicht an. Wir wissen aber, wie dann postinc aussieht:
iterator postinc(){ iterator copy=*this; preinc(); return copy; }
nun sind wir in einer solchen Situation:
for(iterator i=...; i !=...; i++){ }
was passiert?
Der Compiler wird postinc inlinen. Dann wird er merken, dass die Kopie sinnlos ist(und keine Seiteneffekte hat). Dann sagt ihm der Standard, dass er die Kopie raus optimieren kann. Übrig bleibt preinc();//edit ich sags doch: iterator mit shared_ptr. Wozu?!?
-
Heisst das jetze C++ ist garnicht so toll?
-
Wieder mal ein schönes Beispiel dafür, dass die Länge einer Diskussion umgekehrt proportional zu deren Bedeutung ist.
-
camper schrieb:
Wieder mal ein schönes Beispiel dafür, dass die Länge einer Diskussion umgekehrt proportional zu deren Bedeutung ist.
-
//edit ich sags doch: iterator mit shared_ptr. Wozu?!?
Sobald man mit etwas abstrakterem als rohem Speicher arbeitet gehts fast nicht anders. Besonders wenn man mit OS/C-Schnittstellen arbeitet hat man oft Daten, die nicht trivial kopierbar sind. Die C++-Algorithmen erfordern aber alle dass Iteratoren kopierbar sind und die Kopien auch eigenständig funktionieren.
Simples Beispiel: Wie würdest du einen Iterator implementieren, der eine Datei zeilenweise iteriert? Ohne Interna nach außen zu ziehen?
Prominentes Beispiel: Boost.Filesystem, der path_iterator nutzt intern boost::shared_ptr.
-
Ethon schrieb:
Simples Beispiel: Wie würdest du einen Iterator implementieren, der eine Datei zeilenweise iteriert? Ohne Interna nach außen zu ziehen?
Prominentes Beispiel: Boost.Filesystem, der path_iterator nutzt intern boost::shared_ptr.Hmm stimmt. An virtuelle Objekte (im Sinne von: nicht wirklich vorhanden) habe ich da nicht gedacht. Ich würde aber auch in dem Fall behaupten, dass die Operationen die mit den Iteratoren stattfinden an sich schon so teuer sind, dass man auch in dem Fall mit Messungen keinen Unterschied feststellen würde.
Die Frage bei so etwas ist: ist das Aufwand/Nutzen Verhältnis hoch genug, als dass man in irgendeinem Coding Standard schreiben müsste: "übrigens, wir verwenden nur pre-increment in for-Schleifen". So etwas muss umgesetzt und durchgesetzt werden. Und in 99% der Fälle macht die Unterscheidung keinen Unterschied(in meinem Projekt exakt 100%). Da würde ich jetzt auch keinem Anfänger sagen: "++i ist besser", nur damit er dann bei jeder for-schleife anfängt nachzudenken, welche Version denn nun nochmal die Schnellere war. Die Wahrscheinlichkeit ist hoch, dass es a) egal ist und b) die Aufmerksamkeit nur von viel schlimmeren Fehlern geklaut wird.
-
Das ist halt so eine Sache, zu der es ein ganzes Spektrum von Standpunkten gibt.
<- "Pre als default verpflichtend im Firmenstyleguide."(1) <-> "Pre für mich persönlich als default, weil ich dann weniger nachdenken muss."(2) <-> "Ganz egal."(3) <-> "Post als Default weils für mich semantisch irgendwas aussagt."(4) ->
Dass du gegen 1 argumentierst bedeutet natürlich nicht, dass du für 4 bist. Ich steh bei 2, und du?Edit: Ah, jetzt hab ichs, glaub ich. Selbst wenn du beispielsweise bei 2 stündest, könntest du einen Anfänger ja trotzdem damit verschonen. Ich würd in einem Tutorial oder so vermutlich die Postfix-Variante erstmal gar nicht (bzw. nur als Anmerkung) erwähnen und einfach überall Prefix benutzen. Das sollte für den Neuling dann recht einfach sein und auch die, die sich mit komplexeren Iteratoren auskennen (und den von dir erklärten Optimierungen nicht immer trauen, oder es einfach auch schon ohne Optimierung optimal haben wollen), nicht stören.
-
@Dobi:
Also erstmal fehlt mir ein Punkt "post für mich als Default weil ich keinen Grund sehe mich umzugewöhnen" (3.5), und dann ist (4) auch noch nicht das Gegenstück zu (1).
Also "Post als default verpflichtend im Firmenstyleguide." (5)Ich = (3.5)
-
camper++ schrieb:
camper schrieb:
Wieder mal ein schönes Beispiel dafür, dass die Länge einer Diskussion umgekehrt proportional zu deren Bedeutung ist.
Japp. Sieht man schon an ALLEN laengeren Threads im RudP. Und wenn Kleinkinder wie Pi und Hacker mitposten, sinkt das Niveau rapide gegen Null.
-
Kommt es nicht auch darauf an wo man i++/++i benutzten will ?Jenachdem kann man das dann benutzen wie man will.
-
7xCore schrieb:
Kommt es nicht auch darauf an wo man i++/++i benutzten will ?Jenachdem kann man das dann benutzen wie man will.
Ja natürlich, immerhin sind es 2 unterschiedliche Operatoren. Immer den Prefix-Operator zu benutzen ist doch nur darauf bezogen, wenn du für den zurückgegebenen Wert überhaupt gar keine Verwendung hast.
-
Kein einziger von euch hat verstanden, worauf ich eigentlich hinaus will, obwohl es doch so offensichtlich ist. Wenn man i++ sieht, sollte der erste Gedanke sein "Wofür wird hier der Rückgabewert gebraucht". Zumindest bei mir ist das so. Wenn ihr nicht so denkt, ist das euer Fehler.
Ich freue mich schon auf Flames ala "Du siehst deine Meinung als einzig richtige an blafu", aber ist nunmal so, dass meine die einzig logisch sinnvolle und begründbare ist.
-
314159265358979 schrieb:
Wenn man i++ sieht, sollte der erste Gedanke sein "Wofür wird hier der Rückgabewert gebraucht". Zumindest bei mir ist das so. Wenn ihr nicht so denkt, ist das euer Fehler.
Ersetze "Fehler" durch "Problem", dann ist die Aussage nicht verfänglich. So klingt sie arrogant. Durch solche Schnitzer ziehst du die Flamewars magisch an.
Wenn ich "i++" oder "++i" sehe, ist mein erster Gedanke "hier wird inkrementiert". Das ist die primäre Aufgabe. Und auch wenn "++i" eine nette Angewohnheit ist, ist deshalb "i++" nicht böse.
-
Was ist dan der Aussage von PI arrogant?Das einzige was an ihr ist, ist das sie stimmt ?!
-
314159265358979 schrieb:
Wenn man i++ sieht, sollte der erste Gedanke sein "Wofür wird hier der Rückgabewert gebraucht". Zumindest bei mir ist das so. Wenn ihr nicht so denkt, ist das euer Fehler.
Ich denke immer: Warum pre-inc, warum post-inc? Weil: Einen Wert geben ja beide zurück. Aber laut Deiner Definition ist das ja fehlerhaft und ich wälze mich jetzt erst mal demütig im Dreck.