Wie const char* myFunc()?



  • Hi,

    mich interessiert mal ein brennend. Wie ist die Rückgabegeschichte mit "const char *" in der STL realisiert?

    Wenn ich z.B. :

    const char *myFunc()
    {
      std::string Blub = "Blub";
      return Blub.c_str();
    }
    

    ausführe, ist mein "Blub" nach dem Aufruf nicht mehr gültig. Ist ja auch logisch, da "std::string::c_str()" nur einen Pointer auf den Inhalt des lokalen Objekts liefert.
    Also wie wurde das umgesetzt? Nehmen wir als Beispiele mal:
    "const char *std::exception::what()" oder "const char *std::string::c_str()".

    Ein Danke, jetzt schon mal.



  • Klassenmethoden wie c_str() oder what() liefern normalerweise einen Zeiger auf interne Daten des this-Objekts. Ansonsten kannst du auch ein static char-Array zurückgeben oder den Speicher per new anfordern (in dem Fall wäre der Aufrufer verantwortlich, den Speicher freizugeben).

    (und in C++ ist sowas sowieso unüblich - gibt lieber den zusammengebauten std::string aus anstelle seines char*-Puffers)



  • Die benutzen ein Member.
    Wenn Du eine Klasse hast, die so aussieht:

    class Test
    {
    public:
        const char* what() const {return text.c_str();}
    private:
        std::string text;
    };
    

    kannst Du es genauso machen.



  • Bei string::c_str() existiert das string-Objekt ja und gibt nur einen Zeiger auf seinen eigenen Speicher-Inhalt zurück. Der ist dann halt gültig, solange das string-Objekt existiert. Bei deiner Funktion geht ja das string-Objekt beim Ende der Funktion kaputt, dann ist der Zeiger nicht mehr gültig. Das selbe gilt für exception::what(), das hat intern halt auch einen string und solange die exception und damit auch der string darin existiert, ist auch der const char*-Zeiger gültig, den du bekommst 🙂



  • Hmm, also so was ähnliches hatte ich mir schon gedacht. Danke schön. 😃



  • CStoll schrieb:

    ...und in C++ ist sowas sowieso unüblich - gibt lieber den zusammengebauten std::string aus anstelle seines char*-Puffers

    Zu Recht, weil es diese ganezn "Ownership-Probleme" damit gibt. Als Außenstehender weiß ich ja gar nicht, ob ich deleten muss oder nicht darf oder das Zeug überhaupt noch gültig ist....

    vector<char*> glob;
    struct A { // verschiedenen Formen von "interner char-Verwaltung"
       char* internDynBuffer;
       char  internBuffer;
    
       string isInit_Dyn;
       static char* staticDynBuffer;
       string isInit;
       static char staticBuffer[100];
    
       size_t globIndex;
    
       A() {
          strncpy(internBuffer, "Simon2", 100);
    
          internDynBuffer = new char[100];
          strncpy(internDynBuffer, "Simon2", 100);
    
          if(isInit_Dyn == "") {
             staticDynBuffer = new char[100];
             strncpy(staticDynBuffer, "Simon2", 100);
             isInit_Dyn = "true";
          }
          if(isInit == "") {
             strncpy(staticBuffer, "Simon2", 100);
             isInit = "true";
          }
    
          globIndex = glob.size();
          glob.push_back(new char[100]);
          strncpy(glob[globIndex], "Simon2", 100);
       }
       char* get1() const { return internDynBuffer; }
       char* get2() const { return internBuffer; }
       char* get3() const { return staticDynBuffer; }
       char* get4() const { return staticBuffer; }
       char* get5() const { return glob[globIndex]; }
       char* get6() const { return "Simon2"; }
    };
    
    void fill(A const& a, vector<char*>& v) {
       v.push_back(a.get1());
       v.push_back(a.get2());
       v.push_back(a.get3());
       v.push_back(a.get4());
       v.push_back(a.get5());
       v.push_back(a.get6());
    }   
    
    int main() {
       A a;
       vector<char*> v;
       fill(a, v);
    
       {
          B b;
          fill(a, v);
       }
    
       delete v[....// Naaaaa ? Welche sollen/müssen wir denn jetzt löschen ? Welche sind überhaupt gültig ?
    

    😃

    Leider bringen Pointer diese Informationen nicht mit ... weswegen Konstrukte, die das selbst organisieren (z.B. shared-"der Letzte macht das Licht aus"-pointer aber auch std::string), besser sind.

    Gruß,

    Simon2.


Anmelden zum Antworten