Initialisierung von shared_ptr <T> von unique_ptr <T []>
[Follow-up zuDie frage]
Ich habe mich in letzter Zeit ein wenig mit intelligenten Zeigern auf Arrays im C-Stil beschäftigt. Letztendlich habe ich das empfohlene getan und stattdessen intelligente Zeiger auf Vektoren verwendet, aber in dieser Zeit bekam ich ein paar Ratschläge: Verwenden Sie keinshared_ptr<T>
Objekt zum Verwalten eines Arrays, das ursprünglich mit @ erstellt wurmake_unique<T[]>
weil es nicht ruftdelete[]
aber eherdelete
.
Das erschien mir nicht logisch und ich überprüfte beide Coliru und der Standard:
Dieser Code:
#include <iostream>
#include <memory>
int main()
{
std::cout << "start!\n";
auto customArrayAllocator = [](unsigned int num){
std::cout << "custom array allocator\n";
return new int[num];
};
std::cout << "allocator constructed\n";
auto customArrayDeleter = [](int *ptr){
std::cout << "custom array deleter\n";
delete[] ptr;
};
std::cout << "deleter constructed\n";
std::unique_ptr<int[], decltype(customArrayDeleter)>
myUnique(customArrayAllocator(4), customArrayDeleter);
std::cout << "unique_ptr constructed\n";
std::shared_ptr<int>
myShared = std::move(myUnique);
std::cout << "shared_ptr constructed\n";
}
produziert diese Ausgabe:
start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter
Welche scheint darauf hinzudeuten, dass dasunique_ptr<T[]>
Deleter wird an die @ übergebshared_ptr<T>
, wie ich erwartet habe
Aus dem C ++ 14 Standard § 20.8.2.2.1pg. 571 von doc, 585 von pdf
template shared_ptr (unique_ptr && r);
Anmerkun: Dieser Konstruktor darf nicht an der Überladungsauflösung teilnehmen, es sei denn, unique_ptr :: pointer kann in T * konvertiert werden.
Auswirkunge: Entspricht shared_ptr (r.release (), r.get_deleter ()), wenn D kein Referenztyp ist, andernfalls shared_ptr (r.release (), ref (r.get_deleter ()).
Ausnahmesicherheit: Wenn eine Ausnahme ausgelöst wird, hat der Konstruktor keine Auswirkung.
Wenn ich das richtig lese, bedeutet das, dass einshared_ptr
object konstruiert sich aus dem Zeiger und dem Deleter einesunique_ptr
. Darüber hinaus ist es nach meinem Verständnis (von der Antwort auf die ursprüngliche Frage), dass die::pointer
eine Art vonunique_ptr<T[]>
istT*
, das in @ konvertierbar sein sollshared_ptr<T>::pointer
'sT*
. Also sollte der Deleter einfach direkt aus dem @ kopiert werdunique_ptr
Objekt, richtig?
Hat mein Test nur funktioniert, weil er nicht der Funktion von @ entsprichstd::make_shared<T[]>
, oder ist die Syntax
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
eine gute, ausnahmesichere (und sauberere) Alternative zu
std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
und seine Art, wenn ich Boost's @ nicht benutzen kashared array und den Wunsch zu vermeiden, entweder dievector
oder derarray
Header mit meinem Code?