Wenn ich eine boost::shared_array<T>
(oder eine boost::shared_ptr<T[]>
) habe, gibt es eine Möglichkeit, eine boost::shared_ptr<T>
zu erhalten, die mit dem Array teilt?Element von shared_array als shared_ptr?
So zum Beispiel, ich könnte schreiben wollen:
shared_array<int> array(new int[10]);
shared_ptr<int> element = &array[2];
Ich weiß, dass ich nicht &array[2]
verwenden kann, weil es nur int *
geben, und es wäre gefährlich für shared_ptr<int>
einen impliziten Konstruktor hat das wird diesen Typ annehmen. Im Idealfall eine Instanz-Methode auf sie, so etwas wie haben shared_array<int>
würde:
shared_ptr<int> element = array.shared_ptr_to(2);
Leider kann ich nichts dergleichen finden. Es gibt einen Aliasing-Konstruktor unter shared_ptr<int>
, der mit einem anderen shared_ptr<T>
aliasiert, aber kein Aliasing mit shared_array<T>
; so kann ich dies nicht schreiben entweder (es wird nicht kompiliert):
shared_ptr<int> element(array, &array[2]);
//Can't convert 'array' from shared_array<int> to shared_ptr<int>
Eine weitere Option, die ich mit gespielt war std::shared_ptr<T>
(std
statt boost
) zu verwenden. 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 unterbricht, da es versucht, meine std::shared_ptr<T[]>
in einen eigenen implementierungsspezifischen Supertyp umzuwandeln, was nicht mehr möglich ist. (Meins erbt derzeit im Moment nur vom Boost.) 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 potenziell in einem großen Projekt verwenden werden.
template<typename T>
boost::shared_ptr<T> GetElementPtr(const boost::shared_array<T> &array, size_t index) {
//This deleter works by holding on to the underlying array until the deleter itself is deleted.
struct {
boost::shared_array<T> array;
void operator()(T *) {} //No action required here.
} deleter = { array };
return shared_ptr<T>(&array[index], deleter);
}
Das nächste, was ich versuche, werde rüstet 1.53.0 Boost (wir haben derzeit nur 1.50.0), mit shared_ptr<T[]>
statt shared_array<T>
, und auch immer boost
statt std
mit (auch für Nicht-Arrays). Ich hoffe, dies wird dann arbeiten, aber ich habe keine Chance zu versuchen, es noch hatte:
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
Natürlich habe ich immer noch die Instanz-Methode Syntax bevorzugen würden, aber ich denke, ich bin kein Glück mit diesem (kurz Boost modifizieren):
shared_ptr<int> element = array.shared_ptr_to(2);
Hat jemand sonst irgendwelche Ideen?
Ihre Deleter-Idee ist * die * Weise, wie es gemacht werden sollte. Es ist nichts besonders ineffektiv (wenn Sie Zweifel haben, führen Sie ein Experiment mit einem Profiler durch). –
@ n.m. Ich denke, es wird einen neuen Kontrollblock (auf dem Heap) für den neuen 'shared_ptr' erstellen, auf den verwiesen wird. Zugegeben, es ist nicht so schlimm, aber es ist immer noch besser, wenn es den gleichen Kontrollblock teilen kann. :) – entheh
Brauchen Sie überhaupt ein 'shared_array'? Wenn Sie eine 'shared_ptr' (mit entsprechenden Deleter) hatten, könnten Sie die Aliasing-Konstruktoren verwenden. –