Fehlermeldung wenn Instanz ohne new erstellt wird
-
danke auch Dir. Wenn ich eine Instanz mit new erstelle wird der Destruktor nicht aufgerufen und ich muß selber dafür sorgen daß der Speicher wieder freigegeben wird. Und da ich Methoden fremder Klassen über deren Instanzen
// Delegation Instanz der TE-Klasse string render(string templ, map<string,string> stash){ Templating::TE te = Templating::TE(templ, stash); return te.render(); };
zu eigenen Methoden mache kann das sehr schnell unübersichtlich werden. Das ist der Grund auf new zu verzichten, da brauche ich keinen Pointer.
Viele Grüße!
-
Die Syntax um in C++ den Konstruktor aufzurufen ist eigentlich:
// Delegation Instanz der TE-Klasse string render(string templ, map<string,string> stash){ Templating::TE te(templ, stash); return te.render(); };
Dafür brauchst du kein
new
und kein=
.
BeiTemplating::TE te = Templating::TE(templ, stash);
Wird theoretisch, auf der rechten Seite ein Objekt erstellt und dann dem Objekt auf der linken Seite zugewiesen und dafür kopiert. Mit "aktuelleren" (ab C++11) Sprachstandards haben wir "Move Semantics". D.h. es wird nicht unbedingt kopiert, sondern, wenn ein Move Assignment existiert (wird häufig vom Compiler zur Verfügung gestellt), wird das Objekt einfach an die richtige Stelle "geschoben" und fertig.
Edit: Mit neueren C++ Standards (auch ab C++11) kann man auch
Templating::TE te{templ, stash};
schreiben.
-
danke Dir. Noch mal zum Delegieren:
Der Aufruf in der eigenen Klasse sieht so aus:
// in meiner Class Response void start_html(){ string filename = BIN["default"]["tmpldir"]+"/start_html.chtml"; start_html_buffer = my::read_file(filename); start_html_buffer = render( start_html_buffer, STASH ); // delegiert };
Das heißt, daß die TE-Instanz die hinter der delegierten Methode steckt in der eigenen Methode gar nicht sichtbar ist. Ergo kann ich da auch kein delete aufrufen weil ich den Pointer gar nicht habe. Von daher darf die TE-Instanz nicht per new erstellt werden.
Viele Grüße!
-
@_ro_ro
Und wo wir uns den Code schon mal etwas genauer ansehen:Hast du dich mit den Möglichkeiten der Parameterübergabe mal beschäftigt? Sagen dir Referenzen etwas? Deine render Funktion erzeugt beim Aufruf Kopien der Parameter, was insbesondere bei
std::map
schnell teuer werden kann. Lies dich bitte mal in die Thematik pass by value vs. pass by reference ein.
Ich nehme mal an, dasstempl
undstash
nur Kontextinformationen enthalten und nicht beschrieben werden, daher könntest du sie aus Performance-Gründen als const-reference übergeben:std::string render( std::string const& templ, std::map<string,string> const& stash){ Templating::TE te( templ, stash ); return te.render(); };
Wenn die Funktion
TE::render()
als const-deklariert ist kann man auchstd::string render( std::string const& templ, std::map<string,string> const& stash){ Templating::TE const te( templ, stash ); return te.render(); };
schreiben. Und wofür steht TE eigentlich? Finde ich als Klassennamen wenig aussagekräftig, das stört mich schon.
Überhaupt solltest du dich mit dem const-Konzept auseinandersetzen und möglichst alles als const deklarieren, was nach der Initialisierung nicht mehr verändert wird. Und auch das Wiederverwenden von lokalen Variablen ist allgemein ein Codesmell:
void start_html(){ // der Dateiname wird sich während der Bearbeitung wohl nicht mehr ändern, daher kann man ihn const machen std::string const filename = BIN["default"]["tmpldir"]+"/start_html.chtml"; // was genau passiert hier? Warum ist start_html_buffer erst das eine, und dann was anderes? start_html_buffer = my::read_file(filename); start_html_buffer = render( start_html_buffer, STASH ); // delegiert // besser: std::string const html_template = my::read_file(filename); start_html_buffer = render( html_template , STASH ); // delegiert };
-
Ja natürlich, Übergabe per Referenz, schon korrigiert, danke für den Hinweis. TE steht für TemplatingEngine, dafür habe ich einen dedizierten Namespace "Templating" und von daher ist dann auch der Aufruf selbsterklärend
Templating::TE;
Viele Grüße!
-
@_ro_ro sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:
Ja natürlich, Übergabe per Referenz, schon korrigiert, danke für den Hinweis. TE steht für TemplatingEngine, dafür habe ich einen dedizierten Namespace "Templating" und von daher ist dann auch der Aufruf selbsterklärend
Templating::TE;
Viele Grüße!
Finde ich nicht, aber gut.
Renderer
oderRenderingEngine
fände ich besser (nachdem, was ich bisher verstanden habe).
-
eigentlich so
Templating::Simple; // Einfache Platzhalter Templating::Loop; // Loops und Platzhalter
aber ich sehe schon, Ihr bringt mich ganz schön auf Trab
Viele Grüße!
-
@Schlangenmensch sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:
Bei
Templating::TE te = Templating::TE(templ, stash);Wird theoretisch, auf der rechten Seite ein Objekt erstellt und dann dem Objekt auf der linken Seite zugewiesen und dafür kopiert. Mit "aktuelleren" (ab C++11) Sprachstandards haben wir "Move Semantics". D.h. es wird nicht unbedingt kopiert, sondern, wenn ein Move Assignment existiert (wird häufig vom Compiler zur Verfügung gestellt), wird das Objekt einfach an die richtige Stelle "geschoben" und fertig.
Nee. da wird und wurde schon immer der Konstruktor -und nur der Konstruktor- aufgerufen.
-
@Jockelx sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:
@Schlangenmensch sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:
Bei
Templating::TE te = Templating::TE(templ, stash);Wird theoretisch, auf der rechten Seite ein Objekt erstellt und dann dem Objekt auf der linken Seite zugewiesen und dafür kopiert. Mit "aktuelleren" (ab C++11) Sprachstandards haben wir "Move Semantics". D.h. es wird nicht unbedingt kopiert, sondern, wenn ein Move Assignment existiert (wird häufig vom Compiler zur Verfügung gestellt), wird das Objekt einfach an die richtige Stelle "geschoben" und fertig.
Nee. da wird und wurde schon immer der Konstruktor -und nur der Konstruktor- aufgerufen.
Dann sollte @_ro_ro den kompletten code zeigen an dem der fehler tatsächlich auftritt.
Denn aktuell scheint es, dass er nur seine Vermutung welche stelle das problem verursacht haben könnte gepostet hat
-
na, bisher habe ich soweit alles verstanden. Meine Instanzen erhalte ich ganz ohne new und Pointerei jetzt so
CGI cgi; Response response; // Delegation Instanz Templating::Simple string render(const string &templ, const map<string,string> &stash){ Templating::Simple te = Templating::Simple(templ, stash); return te.render(); };
und übergeben werden Referenzen. const habe ich ergänzt wo es angebracht ist, auch in den darunterliegenden Klassen die ich auch umbenannt habe damit der Name schonmal was sagt.
Vielen Dank euch allen !
-
@Jockelx Ja, es wird keine Zuweisung ausgeführt, sondern der Copy ctor aufgerufen. Andernfalls wird aber das Objekt direkt initialisiert.
Siehe copy initialization und direct initialization
-
Aha, jetzt verstanden
// Delegation Instanz der TE-Klasse string render(const string &templ, const map<string,string> &stash){ Templating::Simple te(templ, stash); return te.render(); };
und jetzt Feierabend