Kleine Stilfrage
-
Moin,
in C++ hat man ja die möglichkeit (im gegensatz zu C89) Variablen sozusagen überall zu deklarieren. Man sollte also denken dass es guter Stil ist alle Variablen in einem möglichst kleinen Gültigkeitsbereich zu deklarieren. Allerdings wird hier ja auch immer wieder der Konstruktor neu aufgerufen.
zB.:class MyTest { public: MyTest() { std::cout << "Konstruktor!" << std::endl; } }; int main() { for (std::size_t i = 0; i < 10; ++i) { MyTest instance; } return 0; }Wenn man jetzt davon ausgeht dass die Schleife ziemlich oft durchlaufen wird kann das schon peformance einbrüche geben oder? Und was jetzt? Variable ausserhalb des "for-scopes" deklarieren? Oder lieber eine statische Variable?
-
Es hängt davon ab, was die Klasse leistet. Ist sie sehr klein, dann sollte das nicht beachtenswert sein. Ist die Klasse sehr groß, dann kann das ins Gewicht fallen.
-
Die Frage ist sinnfrei. Wo man die Variable deklariert, ergibt sich doch daraus wie man die Variable verwendet. Und dann stellt sich die Frage garnicht mehr.
-
nobaadi schrieb:
Die Frage ist sinnfrei. Wo man die Variable deklariert, ergibt sich doch daraus wie man die Variable verwendet. Und dann stellt sich die Frage garnicht mehr.
hä?
int main() { MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance } } int main() { for (std::size_t i = 0; i < 10; ++i) { MyClass instance; // do some cool stuff with instance } }
-
Das mit Variablen möglichst nahe an der Verwendung zu deklarieren hängt eng mit dem RAII-Konzept zusammen. Mach dich mal drüber schlau.
Und natürlich muss man Objekte entsprechend einer gescheiten Verwendung deklarieren/initialisieren. In deinem Fall könnte es außerhalb sinnvoller sein, aber am besten einfach mal testen mit Profiler.
-
a) du willst 10x was mit einer Instanz machen
b) du willst 10x eine neue Instanz erzeugenJa haengt davon ab was du beabsichtigst ... das ist von Fall zu Fall unterschiedlich. Deswegen kann es keine bevorzugte Loesung geben. Ob a) oder b) benutzt wird, ist keine Stilfrage!
-
cooky451 schrieb:
nobaadi schrieb:
Die Frage ist sinnfrei. Wo man die Variable deklariert, ergibt sich doch daraus wie man die Variable verwendet. Und dann stellt sich die Frage garnicht mehr.
hä?
int main() { MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance } } int main() { for (std::size_t i = 0; i < 10; ++i) { MyClass instance; // do some cool stuff with instance } }Du verwendest die Variable nicht. "do some cool stuff with instance" ist kein realistisches Problem. Bei realistischen Problemen wird die Frage eigentlich immer vom Problem beantwortet. Das hat wenig mit Stil oder RAII zu tun.
-
Auch in C kannst du Variable überall deklarieren: global für das gesamte Programm oder lokal nur für bestimmte Teile wie Funktionen oder ähnliches. Auch kannst du globale Variable bei Bedarf durch lokale Deklarationen ausser Kraft setzen. Das ist alles noch reines C. Was du machst sind Klassen (C++), die wesentlich mehr können, nämlich Datendeklarationen mit darauf aufbauender Funktionalität zu verbinden. Es macht wenig Sinn, Klassen nur für einzelne Daten ohne jede weitere Funktionalität zu schaffen oder diese in einer for-Schleife ohne erkennbare Unterscheidung der gebildeten Instanzen einzusetzen.
Du hast nach Stil gefragt. Ein solcher Stil wäre z.B class HUND (....); und daraus klar erkennbar gebildete Instanzen wie HUND Dackel; HUND Mops; HUND Pudel; etc.
Zur Vorbeugung: Das wäre C mit Klassen. Die C++ Puristen mögen sich weiter austoben, wenn es uns denn etwas lernt!
-
berniebutt schrieb:
Du hast nach Stil gefragt. Ein solcher Stil wäre z.B class HUND (....); und daraus klar erkennbar gebildete Instanzen wie HUND Dackel; HUND Mops; HUND Pudel; etc.
Zur Vorbeugung: Das wäre C mit Klassen. Die C++ Puristen mögen sich weiter austoben, wenn es uns denn etwas lernt!
Versteht das einer?
-
Jenachdem wie komplex die Klassen sind, könnte sowas schneller sein:
int main() { MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance .... // do some cool stuff with instance instance.putBackIntoFreshlyConstructedState(); } }Andererseits hängt das davon ab wie komplex das
putBackIntoFreshlyConstructedState();ist ... ich würde mich aber erst um sowas kümmern wenn da ein Performance bottleneck identifiziert wurde. Und wenn, dann eher so:int main() { { MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance .... // do some cool stuff with instance instance.putBackIntoFreshlyConstructedState(); } } }damit die MyClass dann auch aufgeräumt ist wenn ich sie sonst nur in der Schleife brauchen würde ... sonst hängt die da im Programm rum obwohl ich sie nimmer brauche!
-
padreigh schrieb:
Andererseits hängt das davon ab wie komplex das
putBackIntoFreshlyConstructedState();ist ...Genau. Meist ist das nämlich gerade die Aufgabe des Konstruktors.
padreigh schrieb:
int main() { { // ... } }Die inneren geschweiften Klammern sind unnötig. Der Scope wird dadurch nicht eingeschränkt.
-
Ich würde sagen: grundsätzlich in der Schleife.
In bestimmten Fällen macht die "putBackIntoFreshlyConstructedState" Variante allerdings schon Sinn. Oft muss sich das Objekt zu Beginn eines Schleifendurchlaufs auch nicht in exakt dem selben Zustand befinden wie ein frisch konstruiertes.
Angenommen man braucht innerhalb der Schleife einen std::vector. Den jedes mal zu zerstören und neu anzulegen ist bloss Performance-Verschwendung.
clear()aufzurufen um den Vektor in einen "ausreichend frischen" Zustand zu bringen, kann da schon Sinn machen.
-
Nexus schrieb:
padreigh schrieb:
Andererseits hängt das davon ab wie komplex das
putBackIntoFreshlyConstructedState();ist ...Genau. Meist ist das nämlich gerade die Aufgabe des Konstruktors.
padreigh schrieb:
int main() { { // ... } }Die inneren geschweiften Klammern sind unnötig. Der Scope wird dadurch nicht eingeschränkt.
Bitte was? Dann kompilier das mal und lass es laufen ....
int main(void) { int i; { for (i=0;i< 10; ++i) std::cout << " hallo"; } std::cout << i << std::endl; { int j; { for (j=0;j< 10; ++j) std::cout << " hallo"; } } std::cout << j << std::endl; }jist da definitiv nicht mehr vorhanden ... und wennjein so dickes Ding ist, das es sich lohnt es VOR der Schleife bekannt zu machen und IN der Schleife wieder auf Startzustand zu stellen, dann würde ich meinen das es sich auch lohnt dieses NACH der Schleife nicht mehr rungeistern zu haben -
-
Schau dir nochmals den Codeteil an, den ich zitiert habe. Die doppelten geschweiften Klammern um alles sind sinnlos.
-
hustbaer schrieb:
Angenommen man braucht innerhalb der Schleife einen std::vector. Den jedes mal zu zerstören und neu anzulegen ist bloss Performance-Verschwendung.
clear()aufzurufen um den Vektor in einen "ausreichend frischen" Zustand zu bringen, kann da schon Sinn machen.Wichtig dabei das KANN.
Denn es kann mit clear ja auch langsamer sein...
-
Shade Of Mine schrieb:
hustbaer schrieb:
Angenommen man braucht innerhalb der Schleife einen std::vector. Den jedes mal zu zerstören und neu anzulegen ist bloss Performance-Verschwendung.
clear()aufzurufen um den Vektor in einen "ausreichend frischen" Zustand zu bringen, kann da schon Sinn machen.Wichtig dabei das KANN.
Denn es kann mit clear ja auch langsamer sein...Theoretisch: ja. Praktisch: kaum.
-
Wenn man allerdings ein "Reset" mit
operator=durchführt, kann es schnell einmal langsamer sein als Destruktion/Neukonstruktion. Alleine schon weil Copy-and-Swap-Implementierungen Letzteres immer tun.Das nur als Ergänzung, weil ich auch schon gesehen habe, dass ein Objekt aus Performancegründen mit
operator=wiederverwendet wird
-
Nexus schrieb:
Schau dir nochmals den Codeteil an, den ich zitiert habe. Die doppelten geschweiften Klammern um alles sind sinnlos.
Wir reden wohl aneinander vorbei. Ich hätte es wohl so formulieren sollen:
int main() { // do something here { MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance .... // do some cool stuff with instance instance.putBackIntoFreshlyConstructedState(); } } // do more here }vs.
int main() { // do something here MyClass instance; for (std::size_t i = 0; i < 10; ++i) { // do some cool stuff with instance .... // do some cool stuff with instance instance.putBackIntoFreshlyConstructedState(); } // do more here }