Fehlermeldung wenn Instanz ohne new erstellt wird



  • Sorry wenn ich nerve,
    ohne Fehler geht das da

      class Foo{
        public: 
        std::stringstream header_stream;
    };
    
    int main(){
        Foo *f = new Foo();
    

    Aber ich will es so

     Foo f = Foo();
    

    und wenn ich das notiere kommen jede Menge Fehlermeldungen die ich nicht verstehe:

    In file included from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\ios:42:0,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\istream:38,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\fstream:38,
                     from C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:5:
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\bits\ios_base.h: In copy constructor 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)':
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\bits\ios_base.h:855:5: error: 'std::ios_base::ios_base(const std::ios_base&)' is private
         ios_base(const ios_base&);
         ^
    In file included from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\ios:44:0,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\istream:38,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\fstream:38,
                     from C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:5:
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\bits\basic_ios.h:67:11: error: within this context
         class basic_ios : public ios_base
               ^
    In file included from C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:10:0:
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\sstream: In copy constructor 'std::__cxx11::basic_stringstream<char>::basic_stringstream(const std::__cxx11::basic_stringstream<char>&)':
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\sstream:655:11: note: synthesized method 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)' first required here 
         class basic_stringstream : public basic_iostream<_CharT, _Traits>
               ^
    In file included from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\ios:43:0,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\istream:38,
                     from c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\fstream:38,
                     from C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:5:
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\streambuf: In copy constructor 'std::__cxx11::basic_stringbuf<char>::basic_stringbuf(const std::__cxx11::basic_stringbuf<char>&)':
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\streambuf:804:7: error: 'std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is private
           basic_streambuf(const basic_streambuf&);
           ^
    In file included from C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:10:0:
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\sstream:65:11: error: within this context
         class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
               ^
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\sstream: In copy constructor 'std::__cxx11::basic_stringstream<char>::basic_stringstream(const std::__cxx11::basic_stringstream<char>&)':
    c:\mingw\lib\gcc\mingw32\5.3.0\include\c++\sstream:655:11: note: synthesized method 'std::__cxx11::basic_stringbuf<char>::basic_stringbuf(const std::__cxx11::basic_stringbuf<char>&)' first required here 
         class basic_stringstream : public basic_iostream<_CharT, _Traits>
               ^
    C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp: In copy constructor 'Foo::Foo(const Foo&)':
    C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:233:7: note: synthesized method 'std::__cxx11::basic_stringstream<char>::basic_stringstream(const std::__cxx11::basic_stringstream<char>&)' first required here 
     class Foo{
           ^
    C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp: In function 'int main()':
    C:\var\www\vhosts\rolfrost.de\httpdocs\cgi-bin\fw.cpp:239:17: note: synthesized method 'Foo::Foo(const Foo&)' first required here 
         Foo f = Foo();
                     ^
    

    Wasn da los? Bitte um Mithilfe ­čśë

    Viele Gr├╝├če!



  • @_ro_ro
    std::stringstream hat keinen Copy-Konstruktor, damit lassen sich auch keine Objekte, die std::string_stream Objekte besitzen kopieren.
    Du k├Ânntest den Copy-Konstruktor und Zuweisungsoperator ├╝berladen, in denen du dann den Inhalt des stringstreams kopierst (siehe hier).



  • @DocShoe sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:

    @_ro_ro
    std::stringstream hat keinen Copy-Konstruktor, damit lassen sich auch keine Objekte, die std::string_stream Objekte besitzen kopieren.
    Du k├Ânntest den Copy-Konstruktor und Zuweisungsoperator ├╝berladen, in denen du dann den Inhalt des stringstreams kopierst (siehe hier).

    Donnerwetter, das ist Fachkompetenz, vielen Dank!!!! Damit mu├č ich mich mal n├Ąher befassen. kriegmer hin ­čśë

    Viele Gr├╝├če!!!



  • @_ro_ro sagte in Fehlermeldung wenn Instanz ohne new erstellt wird:

    Aber ich will es so

     Foo f = Foo();
    

    Wieso in dieser form?
    Um eine Klasseninstanz ohne new zu erzeugen ist folgendes ausreichend (f├╝r dein Beispiel):

    Foo f;
    

    Wenn der Konstruktor der Klasse Parameter erwartet dann sieht das z.b. wie folgt aus:

    class Foo  {
    public:
       Foo(int a) : value(a) {}
    private:
      int value;
    };
    
    Foo f(12);
    

    Wobei deine Form mit C++11 funktioniert (Dank move semantik).
    Seit 4.8.1 von gcc ist C++11 vollst├Ąndig implementiert im compiler nur nicht default aktiv.
    Um c++11 support zu aktivieren wird folgender Parameter beim aufruf der compilers ben├Âtigt:

    -std=c++11
    

    Seit GCC 6 ist der default c++ standard c++14 was ein neuerer standard als c++11 ist.

    Nur ist die Form Foo f = Foo(); nicht notwendig. Und mir ist auch kein Grund bekannt wo diese Form ein nutzen h├Ątte.



  • int f()
    {
       Foo f1; 
       Foo f2 = Foo();
    }
    

    Soweit ich wei├č sind beide Formen identisch und der Compiler sollte den Copy-Konstruktor ├╝berhaupt nicht benutzen, das wundert mich gerade etwas.

    @_ro_ro :
    Welchen Compiler und welchen C++ Sprachstandard benutzt du?



  • @firefly

    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!



  • @_ro_ro

    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 newund kein =.
    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.

    Edit: Mit neueren C++ Standards (auch ab C++11) kann man auch Templating::TE te{templ, stash}; schreiben.



  • @Schlangenmensch

    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, dass templ und stash 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 auch

    std::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
    };
    


  • @DocShoe

    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:

    @DocShoe

    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 oder RenderingEngine f├Ąnde ich besser (nachdem, was ich bisher verstanden habe).



  • @DocShoe

    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



  • @firefly

    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



  • @Schlangenmensch

    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 ­čśë


Log in to reply