Was passiert genau, wenn ich einen Point mit NULL initialisiere?
-
Paul Müller schrieb:
Dann bringen wir halt noch ein weiteres Beispiel, mal sehen welche Begründung die Herren diesmal vorzubringen haben. Wie gesagt der shared_ptr war nur schnell aus dem Hut gezaubert und die zwei Zeiger damit der shared_ptr ansatzweise eine Daseinsberechtigung hatte.
char * vs. std::string
Tachyon schrieb:
Du bist bestimmt auch einer von den Kandidaten die meinen, rohe Arrays sind schneller als ein vector, was?
-
Du verstehst den Punkt einfach nicht, Paul Müller.
Du behauptest, Klassen würden Codebloat mit sich bringen, den man mit Low-Level Datenstrukturen (wie rohe Zeiger oder Arrays) nicht haben würde. Das stimmt aber nur dann, wenn du die zusätzliche Funktionalität, die Klassen mit sich bringen, und sei es "nur" die Sicherheit immer delete aufzurufen, nicht haben möchtest.
Wenn du allerdings auch dafür sorgen möchtest, dass zu jeden new ein delete vorhanden ist, oder dass keine Pufferüberläufe entstehen (char* vs. std::string), dann wird der resultierende Code gleich sein, egal ob du es jetzt mit Klassen oder rein prozedural erledigst (auch wenn Exceptionsicherheit nur mit Klassen erreichbar ist). Dass dem so ist, hat SeppJ in seinem Post schön gezeigt.
-
Das ist nicht richtig. Eine Klasse bietet viel mehr Funktionalität, die ich meist gar nicht benötige. Beispielsweise Checks die unnötig sind, weil die Eigenschaften garantiert sind. Diese werde ich wohl kaum nach programmieren. Beispiel char-Array, da allokiere ich mir die Bytes die ich benötigen könnte, um ein realloc zu vermeiden. Damit ist eine bestimmte Größe garantiert und ich benötige auch kein realloc. Ein std::string bietet dir diese Möglichkeit nicht. Dafür bietet dir der std::string durch seine Flexibilität andere Garantien, die natürlich auf kosten der Laufzeit gehen. Bei einem std::string wird man damit leben können, weil bei Text meist keine mehreren GB an Daten anfallen. Bei einer Funktion die Video-Daten verarbeitet sieht es schon wieder anders aus. Da fallen so gewaltige Datenmengen an, dass selbst für den Menschen ein zusätzlicher Maschinenbefehl spürbar werden kann.
Außerdem scheinen einige zu vergessen, das inlining nur innerhalb einer Übersetzungseinheit funktioniert/funktionieren kann. Es mag Compiler geben, die diese Beschränkung umgehen können, doch der klassische Weg erst compilieren, dann linken, lässt überhaupt keine andere Vorgehensweise zu. Und SeppJ hatte es schon angesprochen alle seine Optimierungen gehen auf Kosten der Compiletime. Wenn man sich aber so die Trends in der Programmierung ansieht geht man lieber auf Kosten der Laufzeit in Richtung Optimierung der Compiletime (zB. Pimpl-Idiom). Ich persönlich finde es auch wesentlich sauberer Klassenbeschreibung und Implementation zu trennen.
-
Wenn deine Klassen mehr tun als du möchtest, dann designst du deine Klassen falsch. Das ist deine Schuld und hat überhaupt nichts mit Code-Bloat und all den anderen falschen Behauptungen auf sich die du in diesem Thread aufgestellt hast.
-
Tachyon schrieb:
Du bist bestimmt auch einer von den Kandidaten die meinen, rohe Arrays sind schneller als ein vector, was?
War zwar nicht an mich gerichtet, aber ich werde trozdem mal darauf antworten.
Ja.Iterator in/decrement ist prinzipiell ein paar cyclen langsamer, da eine addy inc/dec (in form eines pointers) meistens inline sind.
Ctor/Dtor sind auch langsamer als die reine allocation, das obligt aber der
zusätzliche initialisierung von membern wie _myPtr etc. sowie ein paar sicherheitsmechanismen.Der reine (random) zugriff á la (*iterator) ist quasi gleich schnell.
Wenn man eins zwei mal eine vector object (und den basischen iterator) selbst proggt und dabei versucht die gleiche funktionalität wie die aus der stl zu haben sieht man die performance unterschiede.
Was ich z.B. tunlichst vermeide ist, wenn die verwendung von std::vector angebracht ist, in schleifen diesen typ neu zu erzeugen.
while(1) { std::vector<blub> vecBlub; //... } //dann lieber std::vector<blub> vecBlub; while(1) { vecBlub.clear(); //... }
Gerade da kann man sehen was die Ctor/Dtor calls eigentlich an performance kosten.
Verzichtet man zusätzlich auf einen vector und allociert , nicht reallociert, und befreit einen Speicherbereich innerhalb der Schleife, so bekommt man noch einen zusätzlichen performance schub. (<-- realloc ist langsamer, da bei vergrößerung des speicherbereiches erst geguckt wird ob genügen "zusätzlicher" speicher vorhanden ist, oder ein weiter block frei ist mit genügen speicher, dann den speicher vom alten in den neuen block kopiert.)
std::vector aus der stl ist kein schlechtes object und zahlreich handoptimiert sowie für viele einsatzgebiete anwendbar, vlt. sogar empfehlenswert. Aber in vielen Fällen fehlverwendet, was zu Performance einbussen von mehreren 100 000-en cyclen bedeutet.
Greetz
-
Ihr erstellt also alle eure std::strings speziell für jedes eurer Probleme immer wieder aufs neue? Interessant! Ich nutze lieber den Vorteil von C++ und verwende bestehende Klassen wieder. Und da nehme ich auch einen gewissen Overhead in kauf. Ich weiß das man mir aus dem letzten Satz wieder einen Strick drehen will. Ich habe aber nie behauptet, dass das schlecht ist, sondern nur das es da ist und manchmal ungünstig ist. Wie zum Beispiel das Beispiel mit dem shared_ptr gezeigt hat, welches aber niemand kapieren wollte. Aber auch interessant das man wieder nicht auf die Punkt eingehen will und statt dessen lieber so unscharfe Aussagen macht, wie "deine anderen falschen Behauptungen".
Ich tue jetzt dem HighLigerBiMBam einen Gefallen und bin hier raus. Sorry aber das ist doch keine Diskussionskultur nur Argumente zuzulassen, die den eigenen Punkt unterstützen.
-
zeusosc schrieb:
Tachyon schrieb:
Du bist bestimmt auch einer von den Kandidaten die meinen, rohe Arrays sind schneller als ein vector, was?
War zwar nicht an mich gerichtet, aber ich werde trozdem mal darauf antworten.
Ja.Iterator in/decrement ist prinzipiell ein paar cyclen langsamer, da eine addy inc/dec (in form eines pointers) meistens inline sind.
Hrmmm?
zeusosc schrieb:
Gerade da kann man sehen was die Ctor/Dtor calls eigentlich an performance kosten.
Woran? Ich sehe es daran nicht.
zeusosc schrieb:
Verzichtet man zusätzlich auf einen vector und allociert , nicht reallociert, und befreit einen Speicherbereich innerhalb der Schleife, so bekommt man noch einen zusätzlichen performance schub. (<-- realloc ist langsamer, da bei vergrößerung des speicherbereiches erst geguckt wird ob genügen "zusätzlicher" speicher vorhanden ist, oder ein weiter block frei ist mit genügen speicher, dann den speicher vom alten in den neuen block kopiert.)
Realloc ist vor allem deshalb langsamer, weil der alte Speicherbereich in den neuen kopiert werden muss.
zeusosc schrieb:
std::vector aus der stl ist kein schlechtes object und zahlreich handoptimiert sowie für viele einsatzgebiete anwendbar, vlt. sogar empfehlenswert. Aber in vielen Fällen fehlverwendet, was zu Performance einbussen von mehreren 100 000-en cyclen bedeutet.
Weil man halt alles nur dafür verwenden sollte, wofür es designed wurde? Es sei denn, es geht darum fix was zusammenzuflicken...
-
Da hier vieles durcheinander gekommen ist, will ich die Diskussion noch mal zusammen fassen.
SeppJ schrieb:
Paul Müller schrieb:
Objekte verschlimmern diese ganze Angelegenheit auch nur.
Unsinn. Abstraktion kostet keine Laufzeit.
SeppJ schrieb:
Idealerweise programmiert man so, dass solche Probleme gar nicht erst auftreten können.
Paul Müller schrieb:
Das ist meist schwierig, wenn es um zeitkritische Aufgaben geht.
Unsinn. Abstraktion kostet keine Laufzeit.
SeppJ schrieb:
Du hast es ja eigentlich sehr einfach, du brauchst bloß ein Gegenbeispiel zu zeigen, bei dem eine (natürlich nicht absichtlich schlecht programmierte) Klasse auch nur einen Maschinenbefehl mehr benötigt als ein vergleichbarer Code ohne Klasse. Dein Zug.
inlining - nicht immer möglich (nur innerhalb der gleichen ÜE, Begründung steht im Text)
loop unrolling - nicht immer möglich (max. bei inlining)
ungenutzte Member können nicht immer weg optimiert werden, auch bei inline nicht (siehe mein Bespiel mit dem vector)Das sollten wohl genug Argumente sein.
Und danke für die Unterstützung von zeusosc. Ich denke aber Tachyon wollte auf ein paar Eigenschaften eines vectors hinaus, die keine Laufzeitunterschiede kosten. Wie der Zugriff über operator[] oder der Allokierung einer festen Größe.
-
Langsam hab ich den Verdacht, dass Paul Müller nicht weiß, was Abstraktion ist, weil er nicht weiß wie man dies in C++ ausdrückt.
btw:
inlining - nicht immer möglich (nur innerhalb der gleichen ÜE, Begründung steht im Text)
loop unrolling - nicht immer möglich (max. bei inlining)Hast du eh kein Einfluß mehr, darüber entscheidet der Compiler für sich alleine. Höchstens als Hinweis.
ungenutzte Member können nicht immer weg optimiert werden, auch bei inline nicht (siehe mein Bespiel mit dem vector)
Member in eine sind immer genutzt sonst würden sie nicht drin sein. Wer dies Bestreitet, versteht Kapselung auch nicht.
-
Zeus schrieb:
Hast du eh kein Einfluß mehr, darüber entscheidet der Compiler für sich alleine. Höchstens als Hinweis.
Ich weiß. Und dein Hinweis bekräftigt nur meine Aussage, ich hoffe das ist dir aufgefallen.
Zeus schrieb:
Member in eine sind immer genutzt sonst würden sie nicht drin sein. Wer dies Bestreitet, versteht Kapselung auch nicht.
Beispiel hier std::vector. Ein vector hat ein zusätzliches Attribut seiner tatsächlichen Größe. Das braucht aber nur der vector für Optimierungszwecke, um ein rasches realloc zu vermeiden. Wenn ich gescheit programmiere, minimiere ich den Bedarf an reallocs, wo es nur geht.
Das heißt jetzt nicht, dass ich nicht erst mal gescheiterweise selber einen vector verwenden würde.
Was dir vielleicht wieder nicht aufgefallen ist, dass du auch mit diesem Punkt meine Argumentation unterstützt hast.SeppJ schrieb:
du brauchst bloß ein Gegenbeispiel zu zeigen, bei dem eine (natürlich nicht absichtlich schlecht programmierte) Klasse auch nur einen Maschinenbefehl mehr benötigt als ein vergleichbarer Code ohne Klasse.
-
Beispiel hier std::vector. Ein vector hat ein zusätzliches Attribut seiner tatsächlichen Größe. Das braucht aber nur der vector für Optimierungszwecke, um ein rasches realloc zu vermeiden.
So'n Quatsch. Die Größe eines Vektors ist ein Integraler Bestandteil seines Interfaces. Wie sonst sollst du über alle Elemente eine Vektors iterieren, wenn du seine Größe nicht kennst?
Das ist bei Arrays auch nicht anders. Du musst irgendwie die Anzahl der Elemente im Array kennen, sonst kannst du nicht darüber iterieren. Bei mit new angelegten Arrays musst du die Größe explizit speichern, bei Arrays auf dem Stack geht es evtl. noch über sizeof(), solange das Array noch nicht zu einem Pointer zerfallen ist.
Also wieder: Dieses "zusätzliche" Attribut ist gar nicht zusätzlich, da du in jedem Fall bräuchtest.
-
Decimad schrieb:
zeusosc schrieb:
Tachyon schrieb:
Du bist bestimmt auch einer von den Kandidaten die meinen, rohe Arrays sind schneller als ein vector, was?
War zwar nicht an mich gerichtet, aber ich werde trozdem mal darauf antworten.
Ja.Iterator in/decrement ist prinzipiell ein paar cyclen langsamer, da eine addy inc/dec (in form eines pointers) meistens inline sind.
Hrmmm?
Was ist daran unverständlich?
Decimad schrieb:
zeusosc schrieb:
Gerade da kann man sehen was die Ctor/Dtor calls eigentlich an performance kosten.
Woran? Ich sehe es daran nicht.
Ich wiederhole: Wegen der Initialisierung der member und sicherheitsmechanismen. Guckt dir mall den Callstack an. Da wirst du die benötigten aufrufe, sprünge etc sehen.
Decimad schrieb:
zeusosc schrieb:
Verzichtet man zusätzlich auf einen vector und allociert , nicht reallociert, und befreit einen Speicherbereich innerhalb der Schleife, so bekommt man noch einen zusätzlichen performance schub. (<-- realloc ist langsamer, da bei vergrößerung des speicherbereiches erst geguckt wird ob genügen "zusätzlicher" speicher vorhanden ist, oder ein weiter block frei ist mit genügen speicher, dann den speicher vom alten in den neuen block kopiert.)
Realloc ist vor allem deshalb langsamer, weil der alte Speicherbereich in den neuen kopiert werden muss.
Ich habe den verdacht das Du meinen Text nur überfliegst. Das habe ich doch geschrieben oder nicht?
Decimad schrieb:
zeusosc schrieb:
std::vector aus der stl ist kein schlechtes object und zahlreich handoptimiert sowie für viele einsatzgebiete anwendbar, vlt. sogar empfehlenswert. Aber in vielen Fällen fehlverwendet, was zu Performance einbussen von mehreren 100 000-en cyclen bedeutet.
Weil man halt alles nur dafür verwenden sollte, wofür es designed wurde? Es sei denn, es geht darum fix was zusammenzuflicken...
Ich sehe du verstehst was ich meine...
grüße
-
Ich weiß ja nicht, was Du da mit dem vector so treibst, aber bei mir bleibt im Realeasemode nichts mehr von dem Sicherheitsmechanismen übrig. Und die Iteratoren werden zu normalen Zeigern.
-
Ecke schrieb:
So'n Quatsch.
Ja quatsch hast du hier tatsächlich eine Menge zusammen getragen.
Ecke schrieb:
Die Größe eines Vektors ist ein Integraler Bestandteil seines Interfaces. Wie sonst sollst du über alle Elemente eine Vektors iterieren, wenn du seine Größe nicht kennst?
Ich sehe du hast keine Ahnung worum es geht, aber erlaubst es dir dich ziemlich weit aus dem Fenster zu lehnen.
Ecke schrieb:
Das ist bei Arrays auch nicht anders. Du musst irgendwie die Anzahl der Elemente im Array kennen, sonst kannst du nicht darüber iterieren. Bei mit new angelegten Arrays musst du die Größe explizit speichern, bei Arrays auf dem Stack geht es evtl. noch über sizeof(), solange das Array noch nicht zu einem Pointer zerfallen ist.
Also wieder: Dieses "zusätzliche" Attribut ist gar nicht zusätzlich, da du in jedem Fall bräuchtest.
Spätestens als ich realloc geschrieben habe, hättest du hellhörig werden sollen.
Btw. Was soll das sein, ein Array zu einem Pointer zerfallen? Du kannst maximal ein Zeiger auf ein Array haben, aber ein Array ist kein Zeiger und wird auch keiner.
-
Darf ich mir hier kurz die Frage erlauben, warum hier ein dynamisches Array in Form von std::vector mit einem statischem Array verglichen wird? Sollte man da zum Ausgleich nicht lieber std::tr1::array als Vergleich nehmen?
Btw. Was soll das sein, ein Array zu einem Pointer zerfallen? Du kannst maximal ein Zeiger auf ein Array haben, aber ein Array ist kein Zeiger und wird auch keiner.
Ich glaube, genau dass meint er. Also das ein Pointer auf ein Array gerichtet wird.
-
Paul Müller schrieb:
Zeus schrieb:
Hast du eh kein Einfluß mehr, darüber entscheidet der Compiler für sich alleine. Höchstens als Hinweis.
Ich weiß. Und dein Hinweis bekräftigt nur meine Aussage, ich hoffe das ist dir aufgefallen.
Langsam weiß ich nicht, ob ich mit ein Troll oder mit einen der schwer vom Begriff ist.
Ich versuchs trotzdem noch einmal.
Wie kann dein Argument ein Gegenargument wegen den Abstraktionkosten sein, wenn die Fähigkeit zu Inline ausschließlich bei der Implementierung des Kompiler und der Runtime liegt. Die Abstraktion hast du im Code, nicht in der Übersetzung.Sehen wir uns im konrekten Fall vom MS Visual C++ Kompiler an:
Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:
* The function or its caller is compiled with /Ob0 (the default option for debug builds).
* The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).
* The function has a variable argument list.
* The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
* The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions are inlined to a default depth of 16 calls. To reduce the inlining depth, use inline_depth pragma.
* The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
* The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
* The function is also marked with the naked __declspec modifier.
-
Zeus schrieb:
Langsam weiß ich nicht, ob ich mit ein Troll oder mit einen der schwer vom Begriff ist.
Ich würde eher behaupten, dass du nur die Hälfte liest und dir deswegen völlig unnötig die ganze Arbeit machst. Ich weiß was inline macht, wann es angewendet wird und wann nicht. Aber du scheinst einen wichtigen Punkt immer wieder zu überlesen, obwohl ich ihn schon mehrmals hervorgehoben habe.
SeppJ schrieb:
du brauchst bloß ein Gegenbeispiel zu zeigen, bei dem eine (natürlich nicht absichtlich schlecht programmierte) Klasse auch nur einen Maschinenbefehl mehr benötigt als ein vergleichbarer Code ohne Klasse.
Ich extrahiere mal die wichtigen Informationen für dich:
[] auch nur einen Maschinenbefehl mehr
[] als ein vergleichbarer Code ohne KlasseDen ersten Punkt können wir gerne aufweichen. Fakt ist aber, wenn der Compiler nicht inlinen kann, dann muss er die Argumente auf den Stack pushen und die Funktion anspringen, ausführen, zurück springen und irgendwann noch den Stack wieder aufräumen. Ich denke du kannst mir folgen. Die Idee ist aber die Lösung ohne Abstraktion definitiv zu "inlinen". Wir müssen also kein Stack pushen und popen und wir müssen nicht zur Funktion springen und wieder zurück springen. Es sollte klar sein, dass weniger Aufwand, weniger Zeit bedeutet.
-
Ich mach hier mal zu. Die Argumente wurden alle genannt, jetzt dreht sich die Diskussion im Kreis. Deshalb kommen in diesem Beitrag auch keine Fachargumente mehr, sondern ich verweise auf alles was bisher geschrieben wurde.
@Paul Müller: Du denkst jetzt sicherlich, dass ich dies mache um eine unangenehme Wahrheit zu unterdrücken. Ich schreibe kurz noch einen kurzen Text, warum ich zumache, den du nicht einsehen wirst, aber in ein paar Jahren wirst du es vielleicht verstehen:
Dies ist ein Hilfeforum in dem Fragen beantwortet werden. Falsche Aussagen kann man natürlich auch nicht stehen lassen und deine Behauptung wurde korrigiert und sogar tatkräftig widerlegt. Damit sollte sich das Thema eigentlich erledigt haben. Ob du es einsiehst oder nicht ist deine Sache. Man argumentiert nur noch mit dir, weil man dich nicht dumm sterben lassen will. Ich habe den Eindruck du hängst dich nur rein, weil du irgendwie den Thread gewinnen willst. Hier ist eine große Weisheit: Entgegen anders lautender Gerüchte kann man das Internet nicht gewinnen!
Jetzt da "Gewinnen" in diesem Thread aufgrund der Schließung unmöglich ist, kannst du ihn dir ja noch einmal in Ruhe durchlesen, ohne krampfhaft Recht haben zu müssen. Dies ist ein doppelter Gefallen für dich: 1. Lernst du vielleicht etwas wichtiges, 2. machst du dich nicht weiter lächerlich. Ich sehe du bist auch in anderen Threads aktiv und versuchst zu helfen, aber wenn du hier so weiter machst, nimmt dich bald niemand mehr ernst. Das Wort Troll ist schon gefallen.
Du argumentierst in diesem Thread allein gegen das gesamte Forum, gegen viele Jahrzehnte gesammelte C++ Erfahrung. Hier haben Leute gepostet die vermutlich länger programmieren als du lebst. Glaubst du, die haben alle unrecht und du allein auf der Welt hast eine spektakuläre Wahrheit gefunden? Ich weiß, es ist gut, Autoritäten in Frage zu stellen. Aber in Frage stellen heißt auch, kritisch darüber nachzudenken, ob der Rest der Menschheit nicht vielleicht doch Recht haben könnte, wenn man alleine dagegen steht.