"Rohdatentyp"



  • Die Seite zu dem swap() kenne ich schon, allerdings verstehe ich einfach nicht wie mir das jetzt helfen soll.. vielleicht macht sich ja jemand die Mühe und schreibt ein Beispiel..

    Na gut, ich poste einfach noch mal die Klasse - so lernt man wohl am schnellsten 😃

    class MyBuf
    {
    private:
      std::vector<char> m_vector;
    public:
      MyBuf();
      MyBuf(const std::string& text);
      MyBuf(const char* const text);
      void operator = (const std::string& text);
      void operator = (const char* const text);
      char *data();
      void resize(const std::size_t size);
      std::size_t size();
    };
    
    MyBuf::MyBuf()
    {
    }
    
    MyBuf::MyBuf(const char* const text)
    {
      *this = text;
    }
    
    MyBuf::MyBuf(const std::string& text)
    {
      *this = text;
    }
    
    void MyBuf::operator = (const char* const text)
    {
      m_vector.resize(strlen(text) + 1);
      strcpy(&m_vector[0], text);
    }
    
    void MyBuf::operator = (const std::string& text)
    {
      *this = text.c_str();
    }
    
    char *MyBuf::data()
    {
      return &m_vector[0];
    }
    
    void MyBuf::resize(const std::size_t size)
    {
      m_vector.resize(size);
    }
    
    std::size_t MyBuf::size()
    {
      return m_vector.size();
    }
    

    (Und das vector eigentlich gar keinen Member data() hat ist ja mal eine fiese Microsoft Falle ..)



  • Etwas performanter:

    MyBuf::MyBuf() { } 
    
    MyBuf::MyBuf(char const* text) 
    { 
      *this = text;
    } 
    
    MyBuf::MyBuf(std::string const& text) 
    { 
      *this = text; 
    } 
    
    void MyBuf::operator=(char const* text) 
    { 
      m_vector.assign(text, test + strlen(text));
      m_vector.push_back(0); 
    } 
    
    void MyBuf::operator=(std::string const& text) 
    { 
      m_vector.assign(text.begin(), text.end());
      m_vector.push_back(0);
    } 
    
    char* MyBuf::data() 
    { 
      return &m_vector[0]; 
    } 
    
    void MyBuf::resize(const std::size_t size) 
    { 
      m_vector.resize(size); 
    } 
    
    std::size_t MyBuf::size() const 
    { 
      return m_vector.size(); 
    }
    


  • cooky451 schrieb:

    hav a break schrieb:

    cooky451 schrieb:

    Und warum nutzt Du da nicht einfach strlen() ?

    Weil es länger gedauert hätte die richtigen Header zu ergooglen. 😃
    Wird wahrscheinlich cstring sein. Aber man wird auch nicht dümmer, wenn man mal sieht, wie so etwas gemacht wird.

    LOL, den header googlen? Naja gut.. vielleicht nutzt man die Funktion in C++ ja seltener oO

    Ich verwende strlen so gut wie nie. (Und ich weiss auch nicht in welcher Header man strlen findet.)



  • MyBuf::MyBuf(const char* text)
    {
      m_vector.resize(strlen(text));
      strcpy(data(), text);
      //bzw. geht das natuerlich auch viel schoener
    }
    
    MyBuf::MyBuf(const std::string& text)
    : m_vector(text.begin(), text.end())
    {
       m_vector,push_back(0);
       //zb so waere es schoener
    }
    
    MyBuf& MyBuf::operator = (const char* text)
    //2. const ist unnoetig
    {
      MyBuf temp(text);
      swap(temp);
      //copy&swap
      return *this;
      //immer *this returnen
      //damit man weiter arbeiten kann
      //zB a=b=c; oder aehnliches
    }
    
    void swap(MyBuf& other) {
      m_vector.swap(other.m_vector);
    }
    


  • @Shade of Mine: Erstmal alles in einen Vector kopieren nur um swap nutzen zu können?
    Imo sehr fragwürdig.



  • Ethon schrieb:

    @Shade of Mine: Erstmal alles in einen Vector kopieren nur um swap nutzen zu können?
    Imo sehr fragwürdig.

    Du kopierst ja nicht den vector, sondern erstellst ihn.



  • hav a break schrieb:

    Ethon schrieb:

    @Shade of Mine: Erstmal alles in einen Vector kopieren nur um swap nutzen zu können?
    Imo sehr fragwürdig.

    Du kopierst ja nicht den vector, sondern erstellst ihn.

    Argh, stimmt 😉



  • MyBuf::MyBuf(const char* text)
    : m_vector(text, text + strlen(text))
    {
      m_vector.push_back(0);
    }
    //...
    

    Gehts nicht auch so, @Shade?



  • Doch, so gehts auch.



  • Tachyon schrieb:

    Gehts nicht auch so, @Shade?

    Ja.
    Ich habe absichtlich beim 1. ctor die ursprüngliche Variante verwendet und beim 2. dann die korrekte mit initialisierung über iteratoren. Deine Variante ist deshalb auch die bessere.



  • Zwei Fragen hätte ich da noch:

    1. Das hier verstehe ich nicht.. (also warum der Befehl nicht innerhalb der geschweiften Klammern steht)

    MyBuf::MyBuf(const std::string& text)
    : m_vector(text.begin(), text.end())
    {
       m_vector,push_back(0);
       //zb so waere es schoener
    }
    

    2. Welchen Vorteil bringt das swap()? (Außer dass swap() jetzt von Außen zugänglich ist, aber es ging ja hier um den Unterschied zu *this = .. )


  • Mod

    cooky451 schrieb:

    1. Das hier verstehe ich nicht.. (also warum der Befehl nicht innerhalb der geschweiften Klammern steht)

    2. Welchen Vorteil bringt das swap()? (Außer dass swap() jetzt von Außen zugänglich ist, aber es ging ja hier um den Unterschied zu *this = .. )

    Zwei Stichworte zum nachschlagen:
    1. Initialisierungsliste
    2. Copy&Swap Idiom



  • Tachyon schrieb:

    MyBuf::MyBuf(const char* text)
    : m_vector(text, text + strlen(text))
    {
      m_vector.push_back(0);
    }
    //...
    

    Gehts nicht auch so, @Shade?

    In dem Fall geht's sogar noch einfacher:

    MyBuf::MyBuf(const char* text)
    : m_vector(text, text + strlen(text) + 1)
    {
    }
    //...
    

    Und mit "in dem Fall" meine ich ...

    Mit .c_str() würde ich sowas nicht machen, da AFAIK nirgends garantiert wird, dass 2x der selbe Zeiger zurückkommt wenn man 2x hintereinander .c_str() aufruft. Abgesehen davon ginge es mit .c_str() genau so (also m_vector(str.c_str(), str.c_str() + str.size() + 1) ).

    Und ja: vermutlich wird keine vernünftige Implementierung .c_str() so implementieren dass NICHT 2x der selbe Zeiger rauskommt, wenn man den String dazwischen nicht ändert... aber das ist halt keine Garantie.



  • Ok das mit der Initialisierungsliste ist ja wirklich ganz nett und vorteilhaft 🙂
    Das Stichwort Copy & Swap Idiom wurde hier schon mal genannt, allerdings muss ich irgendwie zugeben dass mir die Sinnhaftigkeit immer noch nicht so ganz klar ist..
    Ich glaube das muss man mir noch mal für Blöde erklären 😃

    Abgesehen davon ist mir aufgefallen dass viele hier

    char const* blubb
    

    statt

    const char* blubb;
    

    schreiben. Ist das so eine "C++ Schreibweise"? Weil vorher (C) habe ich das noch nie gesehen..



  • cooky451 schrieb:

    Ich glaube das muss man mir noch mal für Blöde erklären 😃

    Wäre vielleicht noch gut zu wissen, was dir daran Schwierigkeiten bereitet, damit wir nicht den Wikibooks-Artikel wiederholen müssen. Was genau verstehst du nicht?

    cooky451 schrieb:

    Abgesehen davon ist mir aufgefallen dass viele hier [...] schreiben.

    Beide Schreibweisen sind äquivalent. Ich denke nicht, dass eine davon eine spezifische Schreibweise von C++-Programmierern ist.



  • Den Teil "Motivation".



  • Eine Einführung zum Thema Exceptionsicherheit erhältst du im Artikel von Shade Of Mine. Ich empfehle ausserdem das Buch Exceptional C++ von Herb Sutter, darin findest du auch viele andere Tipps zu Programmiertechniken und Design.



  • cooky451 schrieb:

    Den Teil "Motivation".

    Mit Copy & Swap ist es viel einfacher den Assignment-Operator "korrekt" zu implementieren.
    Als Nebenprodukt fällt eine swap() Funktion ab, die auch oft praktisch ist.
    Der Code wird auch gleichzeitig besser wartbar, da man weniger Code wiederholt.


Anmelden zum Antworten