Syntax: typedef struct



  • Sone schrieb:

    mt_struct** & my_mtss;
    

    So etwas exotisches habe ich noch nie gesehen. Gerade als Member... 😮

    Du bist auch kein Three Star Programmer.



  • Was soll ich dazu sagen.

    Wenn ich eine Referenz haben nöchte, dann schaue ich mir an, wie das Objekt initialisiert wird und schreibe & dahinter.

    D.h. wenn dieses ominöse Objekt eben als Pointer auf Pointer initialisiert wird ... dann kommt eben solch eine Konstruktion heraus. 😕

    Gruß,
    -- Klaus.


  • Mod

    Klaus82 schrieb:

    D.h. wenn dieses ominöse Objekt eben als Pointer auf Pointer initialisiert wird ... dann kommt eben solch eine Konstruktion heraus. 😕

    Und deswegen wirst du hier 3-star Programmer "geschimpft". Je nach Sprache gehört um solch ein Monstrum mindestens eine, vielleicht auch mehrere, Abstraktionsschicht aus class, struct, typedef, Makro oder ähnlichem drumherum. Das macht Code kürzer, wartbarer, flexibler, lesbarer, verständlicher, und so weiter. Ich wage sogar zu sagen, dass dir als Programmierer vielleicht erst mit solch einer Abstraktion selber richtig klar wird, mit welcher Art von Objekt du hantierst und wie deine Funktionen dieses Objekt beeinflussen.



  • RealProgrammer schrieb:

    Du bist auch kein Three Star Programmer.

    Ich hatte einen Vorgesetzten, der sogar 5 Sterne-Programmierer war xD



  • Dreisterneprogrammierer ist man erst ab ***. Hier sehe ich kein Problem. Der Zeiger purzelt halt so aus der API raus, solange man damit außer drüber zu iterieren nichts weiter macht, kann der so bleiben.



  • asc schrieb:

    Ich hatte einen Vorgesetzten, der sogar 5 Sterne-Programmierer war xD

    Der Absatz Zeile ist als Rope-Ähnliches Array von Blöcken gebaut, haben wie schon char**, das Kapitel besteht aus Absätzen und der Text aus Kapiteln, char****, mehrere Tabs und char*****, und weil die FileOpen-Funktion das Array der Tabs vergrößern können muss, char******. Das programmier man natürlich heimlich mit Abstraktion und macht die dann kurz vor der Abgabe wieder weg.


  • Mod

    Bashar schrieb:

    Dreisterneprogrammierer ist man erst ab ***. Hier sehe ich kein Problem. Der Zeiger purzelt halt so aus der API raus, solange man damit außer drüber zu iterieren nichts weiter macht, kann der so bleiben.

    Stimme ich nicht zu. Referenzen auf Doppelzeiger sind drei Sterne, mit anderen Mitteln. Hier soll das Doppelzeigerkonstrukt wohl eine Art Typ sein, der eben by reference an die Funktion übergeben wird. Selbst auf niedrigstem Abstraktionsniveau ist hier doch mindestens ein typedef mt_struct** my_object_type; angesagt. Das kostet nichts und bringt so viel.



  • Und davon verschwindet der Zeiger? Was soll das bringen? Der einzige Effekt ist, dass jemand, der die API auch kennt, sich in dem Code nicht mehr ohne zusätzliche Denkarbeit zurechtfindet.



  • SeppJ schrieb:

    Und deswegen wirst du hier 3-star Programmer "geschimpft". Je nach Sprache gehört um solch ein Monstrum mindestens eine, vielleicht auch mehrere, Abstraktionsschicht aus class, struct, typedef, Makro oder ähnlichem drumherum.

    Also eine Art wrapper , wenn ich den Begriff in diesem Zusammenhang richtig deute?

    Gruß,
    -- Klaus.


  • Mod

    Bashar schrieb:

    Und davon verschwindet der Zeiger?

    Ja! Es geht doch nicht da drum, nötige Indirektionen los zu werden. Falls die Indirektion unnötig wäre, wäre das natürlich noch viel schlimmer.

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Der einzige Effekt ist, dass jemand, der die API auch kennt, sich in dem Code nicht mehr ohne zusätzliche Denkarbeit zurechtfindet.

    Nein, ich meine ja auch auf dem Niveau der API. Solch ein Konstrukt sollte bei der Benutzung niemals vorkommen. Das typedef sollte von der API kommen.
    Da kann natürlich klaus82 nichts dafür, wenn die Fremdbibliothek mit solchen komischen Objekten hantiert. Die Beschuldingung der 3-Sterne-Programmierung rührt daher, dass ihm das ganz normal vorkommt und er keine andere Möglichkeit sah.

    klaus82 schrieb:

    Also eine Art wrapper, wenn ich den Begriff in diesem Zusammenhang richtig deute?

    Ja, genau das.



  • SeppJ schrieb:

    Nein, ich meine ja auch auf dem Niveau der API.

    Ihr meint mit API ein application programming interface, also Schnittstelle, ja?

    Dann werde ich mal wieder suchen, denn scheinbar soll solch ein wrapper die Resourcen ganz souverän verwalten, d.h. in meinem Falle initialisieren im Konstruktor, Speicher frei geben im Destruktor und dann eben die Regel der großen Drei beachten und weil es schon C++11 gibt, kann ich gleich den Move- und Assignment operator mitprogrammieren - eine gute Übung.

    Das ist der Fahrplan?

    Gruß,
    -- Klaus.



  • SeppJ schrieb:

    Bashar schrieb:

    Und davon verschwindet der Zeiger?

    Ja!

    Auch wenn mir das jetzt eventuell mitlesende Pascaller übelnehmen: Leute, die zwanghaft Zeiger wegtypedeffen, kann ich nicht ernst nehmen.

    Ich kann verstehen, dass manche sich davon überfordert fühlen. Aber niemand, der gleichzeitig die intellektuelle Kapazität hat, die neuesten Template-Tricks von C++11 nicht nur zu verstehen, sondern auch kreativ anzuwenden. Ich weiß nicht, was das Problem ist, aber ich bin auch kein Psychologe.

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    Nein, ich meine ja auch auf dem Niveau der API. Solch ein Konstrukt sollte bei der Benutzung niemals vorkommen. Das typedef sollte von der API kommen.

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?


  • Mod

    Bashar schrieb:

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    😮 Dazu kann ich nichts mehr sagen. So etwas von dir? typedef ist Abstraktion allererster Güte, die kürzeren, fehlerloseren Code erlaubt, der zudem flexibler gegenüber Änderungen ist. Ohne jeden Nachteil! Wie kannst du das nicht erkennen?

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?

    Habe ich doch gesagt. Eventuell hast du die Erklärung nicht gelesen, da ich sie erst ein paar Sekunden später reineditiert habe.



  • SeppJ schrieb:

    Bashar schrieb:

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    😮 Dazu kann ich nichts mehr sagen. So etwas von dir?

    Ja sicher. Denkst du, dass ich mich von drei hingeworfenen Wörtern beeindrucken lasse? Damit kann man jeden Schwachsinn begründen (und tut es in der Praxis auch, nach den Codierungsrichtlinien zu urteilen, die ich so gesehen habe.)

    typedef ist Abstraktion allererster Güte, die kürzeren, fehlerloseren Code erlaubt, der zudem flexibler gegenüber Änderungen ist. Ohne jeden Nachteil! Wie kannst du das nicht erkennen?

    Schon wieder nur blabla. Was wird denn da kürzer und fehlerloser? Was für Änderungen schweben dir vor? Du glaubst doch nicht wirklich, dass du nur das Typedef ändern musst, wenn die API geändert wird.

    Und siehst du nicht, dass das Teil sogar als Zeiger benutzt wird? Wieso willst du das Wesentliche wegabstrahieren? Das macht man eigentlich, um irrelevantes auszublenden, nicht weil man Angst hat, in Foren als Dreisterneprogrammierer beschimpft zu werden.

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?

    Habe ich doch gesagt. Eventuell hast du die Erklärung nicht gelesen, da ich sie erst ein paar Sekunden später reineditiert habe.

    Äh ja, genau.



  • So,
    ich habe angefangen und habe gesehen, dass seit C++11 die Regel der Drei wohl zur Regel der Fünf geworden ist. 🕶 😃

    Ich habe mit folgender header Datei angefangen

    #ifndef PARALLEL_RNG_H_
    #define PARALLEL_RNG_H_
    
    #include <math.h>
    
    extern "C"
    {
    	#include "dcmt0.6.1/include/dc.h"
    }
    
    struct parallel_rng
    {
    	parallel_rng(int);						// constructor
    	parallel_rng(const parallel_rng&);		// copy constructor
    	~parallel_rng();
    
    	double operator() (int);
    
    	mt_struct** mtss;
    	int N_threads, count;
    	int const seed, w, p, int_max;
    };
    #endif
    

    Jetzt muss ich aber gestehen, dass ich an den Details des Copy Constructors hänge. Denn in Zeile 16 muss ich dieses mt_struct** mtss rüberkopieren, oder nicht?
    Muss ich da nicht mit new arbeiten? Ich versuche es mit dem Wikieintrag zu vergleichen, wo ein Pointer auf einen Array kopiert wird.

    #include <iostream>
    #include "parallel_rng.h"
    
    parallel_rng::parallel_rng(int N_threads):
    N_threads(N_threads),
    seed(18011982),w(32),p(607),int_max(pow(2,w)-1)
    {
    	mtss = get_mt_parameters_st(w,p,1,N_threads,seed,&count);
    }
    /*
    ---{}--- copy constructor ---{}---
    */
    parallel_rng::parallel_rng(const parallel_rng& other):
    N_threads(other.N_threads),count(other.count),
    seed(other.seed),w(other.w),p(other.p),int_max(other.int_max)
    {}
    
    parallel_rng::~parallel_rng()
    {
    	free_mt_struct_array(mtss,N_threads);
    }
    
    double parallel_rng::operator() (int i)
    {
    	return genrand_mt(mtss[i]) / static_cast<double>(int_max);
    }
    

    Gruß,
    -- Klaus.



  • Denn in Zeile 16 muss ich dieses mt_struct** mtss rüberkopieren, oder nicht?
    Muss ich da nicht mit new arbeiten?

    Völlig richtig, gut erkannt. Für eine tiefe Kopie (engl. deep copy), bei der ein neues, unabhängiges Objekt entstehen soll, brauchst du hier eine dynamische Lebenszeit des Objektes.

    ich habe angefangen und habe gesehen, dass seit C++11 die Regel der Drei wohl zur Regel der Fünf geworden ist.

    Richtig. Seit C++11 wird das Konzept von Move-Semantik unterstützt. Das ist was ganz feines, denn so kann man auch Code schreiben, der keine unnötigen Kopien macht.

    wo ein Pointer auf einen Array kopiert wird.

    Na das wäre aber nicht gut, denn dann würde man ja keine tiefe Kopie machen, sondern eben moven. (Da nur die Ressourcen-Zeiger, aber nicht die Ressourcen selbst kopiert werden)



  • Sone schrieb:

    Denn in Zeile 16 muss ich dieses mt_struct** mtss rüberkopieren, oder nicht?
    Muss ich da nicht mit new arbeiten?

    Völlig richtig, gut erkannt. Für eine tiefe Kopie (engl. deep copy), bei der ein neues, unabhängiges Objekt entstehen soll, brauchst du hier eine dynamische Lebenszeit des Objektes.

    Da bin ich gerade überfordert. Wenn ich in meinen C++ Primer schaue unter dem Abschnitt Copy Constructor und Pointer, lande ich sofort bei smart pointern .

    Bei mir kommt erschwerend hinzu, dass ich mt_struct** habe, d.h. Pointer auf Pointer! 😮

    Was mache ich denn da? 😕

    Gruß,
    -- Klaus.



  • new brauchst du trotzdem, das nimmt dir höchstens make_unique / make_shared abnehmen. Das delete ist, was dann wegfällt.

    Bei mir kommt erschwerend hinzu, dass ich mt_struct** habe, d.h. Pointer auf Pointer!

    Wofür genau hast du denn einen Zeiger auf einen Zeiger? Der einzige Grund der mir für doppelte Indirektion (ein Verweis auf einen anderen Zeiger) einfällt ist ein zweidimensionales Array.



  • Klaus82 schrieb:

    Bei mir kommt erschwerend hinzu, dass ich mt_struct** habe, d.h. Pointer auf Pointer! 😮

    Nein. Das, was da erschwerend ist, ist, dass dieser Zeiger von einer Funktion kommt und du nicht weißt, ob das Teil kopierbar ist. Die API:
    http://suchix.kek.jp/guido_cossu/documents/DoxyGen/html/dc_8h.html
    sieht keine Kopierfunktion vor. Man kann in den Quellcode reingucken, das sieht nicht kompliziert aus, also könnte man eine Kopierfunktion bauen. IMHO sollte man sich aber nur nach der Schnittstelle richten. Was heißt das für uns? Entweder den Kopierkonstruktor deleten, oder was mit Referenzzählung basteln.



  • Vielleicht hätte ich mal den Thread zuerst noch einmal lesen sollen... 💡

    Das, was da erschwerend ist, ist, dass dieser Zeiger von einer Funktion kommt und du nicht weißt, ob das Teil kopierbar ist.

    Nun, es hat einen Zeiger auf einen state, daher müsste man den State ebenfalls neu erstellen. Das wars aber eigentlich auch schon.


Anmelden zum Antworten