Einen shared_ptr im konstruktor initialisieren?



  • Hallo, ich habe Probleme mit einem "private member":

    private:
        shared_ptr<vector<shared_ptr<string> > > itsStrings;
    

    "itsStrings" ist also ein "shared_ptr" auf einen Vektor der "shared_ptr" auf "string" speichert.

    Weiter habe ich eine billige Methode die "shared_ptr<string>" an den Vektor hängt:

    public:
        void AddString(const shared_ptr<string>);
    

    Doch bevor diese Methode was tun kann muss ich dem "shared_ptr" aus "private" einen "echten" Pointer auf einen solch o.g. Vektor übergeben. Wie geht das?

    MeinKonstruktor::MeinKonstruktor() {
    
        itsStrings = ???
    }
    

    Besten Dank

    Goran



  • MeinKonstruktor::MeinKonstruktor() : itsStrings(new vector<shared_ptr<string> >)
    {
    }
    

    ??



  • goran schrieb:

    shared_ptr<vector<shared_ptr<string> > > itsStrings;

    Ich hoffe du hast für dieses Monster auch gute Gründe. Ja, ich mag auch die Verwendung von shared_ptr, aber shared_ptr ist ein sehr "teurer" Smartpointer (meist reicht ein std::vector<string> allemal...).

    cu André



  • Danke, hat geklappt. Zum ersten mal das ich die Dinger verwende.

    Wie "teuer" oder wieviel Byte kostet so ein "shared_ptr"? 32 Bit wie bei einfachen Pointer kann es sicher nicht sein.



  • goran schrieb:

    Danke, hat geklappt. Zum ersten mal das ich die Dinger verwende.

    Wie "teuer" oder wieviel Byte kostet so ein "shared_ptr"? 32 Bit wie bei einfachen Pointer kann es sicher nicht sein.

    Es hat zwar auch mit der größe, aber vielmehr mit dem Verwaltungsaufwand zu tun. Zum einen handelt es sich nicht um ein, sondern effektiv um mehrere Objekte (Es gibt ein gemeisamen Datenbestand der ja geteilt wird). Bei der Zuweisung wird ja auch mit Referenzzählung etc. hantiert.

    Und es ist eigentlich ohnehin ungewöhnlich einen vector-Zeiger zu haben (kann Sinn machen, ist aber die Ausnahme). Und je nach Anwendung macht es meistens auch keinen Sinn Zeiger auf strings zu halten.

    Ich kenne deinen Fall nicht, aber in der Regel macht ein std::vectorstd::string mehr Sinn als die Zeigervarianten (sofern man darauf achtet Kopien so weit wie möglich zu vermeiden).

    cu André



  • Ich verstehe. Aber dennoch wundere ich mich über meine bisherige Meinung.

    Ist es nicht so das im Grunde alles was größer als 32 Bit ist (bzw. 64 Bit bei x64) auf den Heap gehört bzw. als Pointer realisiert werden sollte?



  • In der Regel werden std::string & std::wstring intern bereits geshared und nur bei der Mutation des Speichers wirklich kopiert. Ein shared_ptr im vector ist vergleichsweise teuer, allerdings macht es noch nicht so viel aus wenn du nicht andauernd darauf zugreifen musst. Wenn du Angst hast dass die Kopieroperationen von shared_ptr länger dauern weil er grösser als ein normaler Zeiger ist (er besetzt soweit ich informiert bin mindestens 2 Zeiger), kannst du auch auf intrusive_ptr ausweichen; dort hast du im Prinzip genau einen Zeiger pro Handle. Das wäre ein wenig schneller, aber auch nicht signifikant.

    goran schrieb:

    Ist es nicht so das im Grunde alles was größer als 32 Bit ist (bzw. 64 Bit bei x64) auf den Heap gehört bzw. als Pointer realisiert werden sollte?

    Wo hast du denn sowas gehört? Ob etwas auf den Heap oder den Stack gehört hat in den meisten Fällen nicht viel mit der Grösse eines Objektes zu tun. Es geht dabei eher um die Semantik (also Freigabe der Instanz z.b.)



  • goran schrieb:

    Ich verstehe. Aber dennoch wundere ich mich über meine bisherige Meinung.

    Geht nicht nur Dir so... 🙂

    goran schrieb:

    Ist es nicht so das im Grunde alles was größer als 32 Bit ist (bzw. 64 Bit bei x64) auf den Heap gehört bzw. als Pointer realisiert werden sollte?

    Nein. Ob Heap oder Stack hat vielmehr etwas mit der Lebensdauer der Objekte zu tun.

    Simon



  • Statt std::vector<shared_ptr<T> > ist häufig boost::ptr_vector<T> zu empfehlen.
    Der kann den Zeiger auch wieder freigeben, so das man ihn dann z.B. in einen shared_ptr packen kann.



  • ein shared_ptr gehoert nicht in einen container. daufer gibt es die ptr_container in boost.

    aber: jeder STL Container hat sein eigenes memory management und speichert sowieso alles immer auf dem heap.

    es ist loeblich was du dir gedacht hast, aber es ist leider falsch. alles immer auf den stack packen und nur dann wenn du selber bestimmen willst wann es erstellt und zerstoert werden soll - dann auch den heap.



  • Oder wenn es keine Platz auf dme Stack hat.



  • Vielen Dank für die Hinweise. Ich werde sie berücksichtigen. Aber eine Frage hätte ich noch:

    Und zwar wie steht die Sache mit der Rückgabe von "private member" die auf dem Stack liegen?

    Wenn eine "Getter" Methode solch einen "member" zurück gibt wird dieser ja kopiert. Ist das ok oder gibt es bessere Wege? Klar, ist das Ding mehrere MB groß mach' ich das mit einem Pointer. Aber wie ist's bei einem kurzen String?

    Gruß, Goran



  • const ref



  • Shade Of Mine schrieb:

    ein shared_ptr gehoert nicht in einen container. daufer gibt es die ptr_container in boost.

    Das würde ich so definitiv nicht unterschreiben, oder unterstützen die ptr-Container von boost die Referenzzählung der shared_ptr wenn man diese an mehreren Stellen verwendet... Nur man sollte immer abwägen was sinnvoller ist.



  • ein shared_ptr gehoert nicht in einen container. daufer gibt es die ptr_container in boost.

    Hast du dafür auch bessere Argumente als bloss ... naja, nichts?
    Was so schlimm daran einen shared_ptr in einen Container zu stecken?


Anmelden zum Antworten