Diverse Style-Fragen
-
Hi,
ich habe diverse Stylefragen:
1. Sollte man auf selbstdefinierte datentypen verzichten?
z.B.:unsigned short *getBuffer (void); // vs USHORT *getBuffer (void);
2. Inline Funktionen in klassen, Was ist besser und warum?
inline RGB_INFO*getRgbInfoPtr (void) { return (&m_rgbInfo); } // vs RGB_INFO*getRgbInfoPtr (void) { return (&m_rgbInfo); }
3. __forceinline vs inline: Was und warum?
4. Alle klassen, egal wie Popelig, auf den Stack oder Heap legen?
5. Templateklassen auch für Klassen wie einen math::vector3d?
6. Funktionen ohne Klasse in einem Namespace erlaubt?
-
1.geschmacksache. ich verzichte lieber
2.falls sich die implementierung im header befindet is die funktion automatisch inline
bei inline funktionen wird d er code an die stelle kopiert an der er gebraucht wird
damit spart man sich einen oder mehrere sprünge an die codestelle
is sinnvoll bei kleinen funktionen
stell dir 100 funktionsaufrufe vor die jeweils nur eine anweisung haben
wenn die nich inline sind kommen zu den 100 anweisungen noch 100 sprünge3.inline lässt den compiler entscheiden ob es wirklich sinnvoll is
__forceinline zwingt den compiler
d.h. du solltest __forceinline benutzen wenn du denkst du hast mehr ahnung von den internen abläufen als der compilerprogrammierer4.heap is halt grösser. is n altes thema->suchfunktion
6.denke schon... warum nich?
-
1. bei den trivialen Typen besser keine Typedefs, aber das is wirklich geschmackssache(dann aber bitte nicht die typen GROSS schreiben).
4.stack ist schneller, also soviel darein wie möglich, den heap nur da benutzen, wo er wirklich gebraucht wird(und auch da eher gekapselt, damit das delete nich vergessen wird)
6. ja, aber wirklich nur im namespace
-
*** schrieb:
1. Sollte man auf selbstdefinierte datentypen verzichten?
z.B.:unsigned short *getBuffer (void); // vs USHORT *getBuffer (void);
In dem Fall ja, da USHORT ja nur ein Synonym for unsigned short ist und keinerlei Abstraktion einführt.
2. Inline Funktionen in klassen, Was ist besser und warum?
inline RGB_INFO*getRgbInfoPtr (void) { return (&m_rgbInfo); } // vs RGB_INFO*getRgbInfoPtr (void) { return (&m_rgbInfo); }
Die Definitionen sind identisch.
4. Alle klassen, egal wie Popelig, auf den Stack oder Heap legen?
Alles auf den Stack, solange du das Objekt nicht über die Funktionsgrenzen hinweg brauchst. Einzige Ausnahme sind wirklich riesige statische Arrays (und auch nur die) als Klassenelemente.
5. Templateklassen auch für Klassen wie einen math::vector3d?
Mach doch einfach ein template draus, wenn du es brauchst. Ohne Bedarf mache ich meinen Code jedenfalls nicht unübersichtlicher.
6. Funktionen ohne Klasse in einem Namespace erlaubt?
Klar. Was nicht unbedingt Zugriff auf die Klassen-Eingeweide braucht, kann immer gerne eine freie Funktion sein. Damit ist die Kapselung der Klasse besser geschützt.
-
Sollte man auf selbstdefinierte datentypen verzichten?
nein, natürlich nicht. Nur du solltest typedef benutzen (und nicht wie einige Vögel #define) und komplett groß geschriebene Typen sind einfach hässlich und lenken IMHO beim lesen zu sehr ab.
3. __forceinline vs inline: Was und warum?
__forceinline ist irgend eine MSVC++ Erweiterung. Wenn du portabel sein willst, solltest du das nicht benutzen
(oder lieber so
#ifdef __MSVC__ #define FORCEINLINE __forceinline #else #define FORCEINLINE inline #endif
)
Ansonsten halte ich __forcedinline für nicht sehr praktisch, da der Compiler schon seine Gründe hat, wenn er etwas nicht inlinen will.
-
Typedefs bei simplen Typen sind manchmal nutzlich und retten dir den A...
Besonders wenn man mit ned ganz so entschlussfreudigen mitprogrammierern arbeitet, die so in ihren Schnittstellen haeufig zwischen den typen umherswitchen (sind die im eigenen Project, sollte man denen eh auf die finger haun !), und man ned staendig mit neuen Compilerwarnings ueberflutet wird (ja, gibt auch noch leute die achten drauf, das ihr project ohne warnings compiliert wird
)
Ich hab mir prinzipiell angewoehnt, fuer datentypen mit spezieller Aufgabe, typedefs zu nehmen und zur verfuegung zu stellen. Beispiele Timestamps, Flag-Typen, etc.
Nichts ist ekliger, als wenn der Projektleiter bestimmt, dass timestamps nimmer 32 bittig, sondern aus kompatiblitaetsgruenden 64 bittig sein muessen, und man sucht dann tagelang alle code nach temp variablen durch :p
Ausserdem findet man die stellen besser, wenn die typen nen eindeutigen namen haben.Prinzipiell:
Temporaere Variablen usw aufn stack legen, wenn sie ned die groesse sprengen ...
Klassen fast immer so programmieren, das man sie aufn stack verwenden kann (schnelle CCtoren, Zuweisungsops etc), solange sie ned zu gross werden.
Werden die Klassen zu gross, dann wirst um den heap ned drumherumkommen. Auch wenn du viele klassen einer Sorte anlegen willst. Aber Wrapper und container helfen dir dann weiter, wo die wrapper / containerklasse normal aufm Stack umherkopierst, die eigentlichen Daten aber aufn heapspeicher bleiben ...
SmartPointer verwenden !!!
Lokale Instantiierung und wertuebergabe (bei temporaeren objecten) / uebergabe per referenz (bei langlebigen objecten) ist Imho besserer C++ Stil als das zeiger geroedele
Wenn der Code aussieht wie der Sternenhimmel bei Nacht ( *******) dann sieht das ned wirklich nach C++ aus5. weiss ned genau was du meinst ?
Templates sind nuetzlich. Aber templates sind auch ne philosophie ! Container Templates sind nur der Anfang. So richtig intressant wirds erst mit Policies / traits.
Diese Technicken helfen dir, deinen Code sehr modular zu halten, und gleichzeitig sehr universell (Baukasten prinzip), und unnötige Polymorphie zu vermeiden.
Aber ned uberall machen Templates gleich sinn
Auf alle faelle isses Wert sich da tiefer reinzuknien, und es hilft sehr viel das design zu verbessern.Ciao ...
-
RHBaum schrieb:
Temporaere Variablen usw aufn stack legen, wenn sie ned die groesse sprengen ...
Klassen fast immer so programmieren, das man sie aufn stack verwenden kann (schnelle CCtoren, Zuweisungsops etc), solange sie ned zu gross werden.
Werden die Klassen zu gross, dann wirst um den heap ned drumherumkommen.Prinzipielle Zustimmung, aber was ist denn "zu groß"? Ein paar hundert Bytes machen den Kohl nicht fett, und das ist IMHO schon sehr groß, es sei denn, deine Klasse sehen so aus:
class Foo { Bar b[10000]; };
In diesem Fall greift wieder die Regel, dass man große Arrays möglicherweise auf dem Heap anlegen sollte.
Auch wenn du viele klassen einer Sorte anlegen willst.
Also ein Array? Die Regel hatten wir schon.
normal aufm Stack umherkopierst, die eigentlichen Daten aber aufn heapspeicher bleiben ...
SmartPointer verwenden !!!Jepp!
Wenn der Code aussieht wie der Sternenhimmel bei Nacht ( *******) dann sieht das ned wirklich nach C++ aus
Wie romantisch
-
wat sind denn smartpointer?
-
aber was ist denn "zu groß"?
Naja, genau da wuerd ich mich eben ned mit zahlen festlegen wollen.
meist tritt die frage eh in zusammenhang mit containern / arrays auf ...
Variable aufm stack halten, und der container sammelt die aufn Heap.
Da kann man eine zusaetzliche kopie nicht wirklich durch referenzen umgehen.
in einigen faellen (wenns wirklich schnell gehen muss) sind paar 100byte schon zu viel. In einigen faellen ists aber auch wirklich schnurz.
In allen faellen eben, wenns ned notwendig ist, schnell zu sein, lieber den Sichereren weg ueber die kopie.@---
google eben mal, denk schon das das nen gebraeuchlicher begriff ist ....
fuers verstaendiss.
Klassen, die dir nen Zeiger wrappen, und sich selber (nur fast, weil viel mehr funktionalitaet) benehmen wie Zeiger ...Ciao ...
-
RHBaum schrieb:
aber was ist denn "zu groß"?
Naja, genau da wuerd ich mich eben ned mit zahlen festlegen wollen.
meist tritt die frage eh in zusammenhang mit containern / arrays auf ...
Variable aufm stack halten, und der container sammelt die aufn Heap.
Da kann man eine zusaetzliche kopie nicht wirklich durch referenzen umgehen.
in einigen faellen (wenns wirklich schnell gehen muss) sind paar 100byte schon zu viel. In einigen faellen ists aber auch wirklich schnurz.
In allen faellen eben, wenns ned notwendig ist, schnell zu sein, lieber den Sichereren weg ueber die kopie.Von Übergabe des Objekts (per Kopie oder per Referenz) hat keiner was gesagt. Nochmal ein Beispiel:
void foo() { Bar b; // bla bla }
Wann ist Bar zu groß, um b auf den Stack zu packen? IMHO nie.
-
Also unter MSVC 6 ist der Stack per default 1MB gross. Den Speicherplatz kann man ganz schnell verbraten wenn mann nicht aufpasst.
long Spielfeld[100][100][100]; // und schluss
Also mit "nie zu gross" wäre ich vorsichtig.
mfg JJ
-
dein spielfeld würde ich auch eher in den heap packen
-
Ich ja auch
wollte nur zeigen wie leicht man den Stack dicht kriegt.
-
1003*4 is ja nich viel :p
-
John Doe: Der Fall, dass Bar ein Array ist, wurde schon ausgeschlossen bzw. anders behandelt. Lies einfach den Thread von vorne.
-
Hi Bashar,
Um ne Variable mit nem Speicherbedarf von mehr als x KB zu erzeugen gibts auch andere Möglichkeiten als ein Array. Ich bin, wie du, auch der Meinung das der Stack die erste Adresse für Variablen ist. Aber ich hoffe es ist nicht so schlimm das ich darauf hingewiesen hab das der Platz nicht unbegrenzt ist, und man hin und wieder überlegen sollte ob der Stack wirklich der richtige Platz ist.
Deswegen halte ich den Hinweis aufgrosse Klassen...
für durchaus sinnvoll.
mfg JJ
-
John Doe schrieb:
Um ne Variable mit nem Speicherbedarf von mehr als x KB zu erzeugen gibts auch andere Möglichkeiten als ein Array.
Aber auch realistische Möglichkeiten? Wenn du in jeder Klasse immer alle Arrays auf dem Heap hast, dann beinhalten Klasse immer nur primitive Typen (Größe 1 bis 10 Byte) oder andere Klassen, du musst also verdammt viel tippen um auf solche Größen zu kommen ... Ich bezweifle dass solche Monsterklassen von einem durchdachten Design zeugen.
-
RHBaum schrieb:
Beispiele Timestamps, Flag-Typen, etc.
für Timestamps würde ich sogar eine Klasse nehmen
RHBaum schrieb:
Ausserdem findet man die stellen besser, wenn die typen nen eindeutigen namen haben.
jo
RHBaum schrieb:
SmartPointer verwenden !!!
Lokale Instantiierung und wertuebergabe (bei temporaeren objecten) / uebergabe per referenz (bei langlebigen objecten) ist Imho besserer C++ Stil als das zeiger geroedele
Wenn der Code aussieht wie der Sternenhimmel bei Nacht ( *******) dann sieht das ned wirklich nach C++ ausfull-ACK
John Doe schrieb:
Also mit "nie zu gross" wäre ich vorsichtig.
Ja, aber wenn die Klasse zu groß ist um auf den Stack gelegt zu werden, dann muss sie intern eben den Heap benutzen
-
mit "zu gross" meint ich ned, das es zu gross fuer den Stack wird, sondern dass die klasse (sprich die Member Variablen) so viel und gross werden, dass es eben unperformant wird.
ne simple 3D punkt klasse mit 3 doubles ist noch kein Problem, wenn man die bei jeder uebergabe kopiert.
Nen Konstrukt aus paar Namen (strings, zur einfachheit halber vielleicht statisch als array mit fester Groesse) und noch zigdutzend statusvariablen, dann wirds schon kritischer. In vielen faellen immer noch schnurz, in manchen aber schon relevant fuer die performance.Dort lieber nen Wrapper (oder smartpointer) schreiben, der das teim aufn heap construiert und nur den verweis aufn stack umherschiebt ...
Ciao ...
-
RHBaum schrieb:
Dort lieber nen Wrapper (oder smartpointer) schreiben, der das teim aufn heap construiert und nur den verweis aufn stack umherschiebt ...
verstehe ich nicht.
einfach referenzen nehmen und nicht immer rumkopieren.ein new dauert doch unendlich länger als ein allokation auf dem stack...