Element von shared_array als shared_ptr?

8

Wenn ich ein boost::shared_array<T> (oder ein boost::shared_ptr<T[]> ) habe, gibt es eine Möglichkeit, ein boost::shared_ptr<T> zu erhalten, das sich mit dem Array teilt?

Zum Beispiel möchte ich vielleicht schreiben:

%Vor%

Ich weiß, dass ich &array[2] nicht verwenden kann, weil es nur den Typ int * hat, und es wäre gefährlich für shared_ptr<int> , einen impliziten Konstruktor zu haben, der diesen Typ annimmt. Idealerweise hätte shared_array<int> eine Instanzmethode, etwa:

%Vor%

Leider kann ich so etwas nicht finden. Es gibt einen Alias-Konstruktor für shared_ptr<int> , der mit einem anderen shared_ptr<T> aliasiert, aber kein Aliasing mit shared_array<T> ; also kann ich das auch nicht schreiben (es wird nicht kompiliert):

%Vor%

Eine weitere Option, mit der ich gespielt habe, war die Verwendung von std::shared_ptr<T> ( std anstelle von boost ). Die Spezialisierung für T[] ist nicht standardisiert, also habe ich darüber nachgedacht, das selbst zu definieren. Leider glaube ich nicht, dass dies tatsächlich so möglich ist, dass es die Interna des Alias-Konstruktors nicht durchbricht, da es versucht, mein std::shared_ptr<T[]> auf seinen eigenen implementierungsspezifischen Supertyp zu werfen, was nicht mehr möglich ist. (Meine erbt momentan nur von der Boost-Version.) Das Schöne an dieser Idee wäre gewesen, dass ich meine Instanz shared_ptr_to Methode implementieren könnte.

Hier ist eine andere Idee, mit der ich experimentiert habe, aber ich denke nicht, dass sie effizient genug ist, um als etwas akzeptiert zu werden, das wir möglicherweise in einem großen Projekt verwenden werden.

%Vor%

Als nächstes werde ich auf Boost 1.53.0 upgraden (wir haben derzeit nur 1.50.0), indem wir shared_ptr<T[]> anstelle von shared_array<T> benutzen und immer auch boost anstelle von% co_de verwenden % (auch für Nicht-Arrays). Ich hoffe, das wird dann funktionieren, aber ich hatte noch keine Gelegenheit, es zu versuchen:

%Vor%

Natürlich würde ich immer noch die Syntax der Instanz-Methode bevorzugen, aber ich denke, ich habe kein Glück damit (kurz, Boost zu modifizieren):

%Vor%

Hat noch jemand Ideen?

    
entheh 21.03.2013, 13:50
quelle

3 Antworten

1

Du machst seltsame Sachen. Warum brauchst du shared_ptr zu Element? Möchten Sie, dass das Element des Arrays irgendwo anders übergeben wird und halten Sie Ihr Array vor dem Entfernen?

Wenn ja, dann ist std::vector<shared_ptr<T>> dafür besser geeignet. Diese Lösung ist sicher, Standard und feinkörnig bei der Entfernung von Objekten

    
kassak 21.03.2013 14:06
quelle
0

boost::shared_ptr scheint das nicht zu unterstützen. Vielleicht können Sie dies mit einem benutzerdefinierten Deleter umgehen. Aber std::shared_ptr bietet einen speziellen Konstruktor, der unterstützt, was Sie wollen:

%Vor%

Hier ist sp1 und sp2 Eigentümer des foo -Objekts, aber sp2 zeigt auf ein Mitglied davon. Wenn sp1 zerstört wird, bleibt das Objekt foo noch aktiv und sp2 ist weiterhin gültig.

    
sellibitze 21.03.2013 14:23
quelle
0

Hier ist, was ich am Ende gemacht habe.

Ich habe meine eigene Implementierung von shared_array<T> gemacht. Es erweitert effektiv shared_ptr<vector<T>> , außer dass es tatsächlich meinen eigenen Wrapper für vector<T> erweitert, so dass der Benutzer den Vektor nicht herausbekommen kann. Dies bedeutet, dass ich garantieren kann, dass die Größe nicht geändert wird. Dann habe ich die benötigten Instanzmethoden implementiert - inklusive weak_ptr_to(size_t) und natürlich operator[] .

Meine Implementierung verwendet std::make_shared , um den Vektor zu erstellen. Daher ordnet der Vektor seinen internen Array-Speicher getrennt vom Steuerblock zu, aber der Vektor selbst wird ein Mitglied des Steuerblocks. Es ist also ungefähr gleichbedeutend mit dem Vergessen, std::make_shared für einen normalen Typ zu verwenden - aber da dies Arrays sind, sind sie wahrscheinlich groß und wenig, also ist es weniger wichtig.

Ich könnte auch eine Implementierung erstellen, die auf shared_ptr<T> basiert, aber mit default_delete<T[]> oder was auch immer benötigt wird, aber das Array muss separat vom Kontrollblock zugewiesen werden (es gibt also nicht viel gegen Vektor). Ich denke nicht, dass es einen portablen Weg gibt, um ein dynamisch sortiertes Array in den Kontrollblock einzubetten.

Oder meine Implementierung könnte auf boost::shared_array<T> basieren und den benutzerdefinierten Deleter verwenden, wenn Sie Elementzeiger verwenden (wie im Beispiel in der Frage). Das ist wahrscheinlich in den meisten Fällen schlimmer, denn statt eines einmaligen Treffers, der das Array zuweist, erhalten wir jedes Mal einen Treffer, wenn wir einen Alias-Zeiger nehmen (was bei sehr kurzlebigen Pointern häufig passieren kann).

Ich denke, der einzige vernünftige Weg, um es noch optimaler zu machen, wäre, den neuesten Boost zu benutzen (wenn es funktioniert; ich habe es nicht so weit versucht), bevor ich meine Meinung geändert habe, hauptsächlich wegen des Verlangens nach meinem eigene Instanzmitglieder). Und das bedeutet natürlich, dass Sie die boost -Einheiten überall verwenden, sogar für einzelne Objekte.

Aber , der hauptsächliche Vorteil, mit dem ich gearbeitet habe, ist, dass Visual Studio's Debugger (wie ich gesagt habe) gut darin ist, den Inhalt von std :: shared_ptrs und std :: vectors anzuzeigen und (wir erwarte) weniger gut darin, den Inhalt von Boost - Dingen oder anderen Dingen zu analysieren.

Also ich denke, was ich gemacht habe, ist im Grunde optimal. :)

    
entheh 21.03.2013 23:16
quelle

Tags und Links