Jak: vytvoření a použití instance shared_ptr
shared_ptr Typ je inteligentní ukazatel v standartní knihovny jazyka C++, který je určen pro scénáře, ve kterých může mít více než jednoho vlastníka, dobu trvání objektů v paměti.Poté, co je inicializovat shared_ptr ji zkopírovat, předat podle hodnoty v argumentech funkce a přiřadit k jiné shared_ptr instance.Všechny instance přejděte ke stejnému objektu a sdílet přístup k jedné "řídicí blok", která zvýší a sníží počet odkazů, vždy, když je nový shared_ptr je přidána, dostane mimo rozsah nebo je obnovit.V případě, že počet odkazů dosáhne nuly, řídicí blok odstraní prostředky paměti a sám.
Následující ilustrace znázorňuje několik shared_ptr instance, které odkazují na umístění v paměti jeden.
Příklad
Kdykoli je to možné, použijte make_shared (<memory>) funkce pro vytvoření shared_ptr při vytvoření prostředku paměti poprvé.make_sharedje bezpečný pro výjimky.Používá stejné volání přidělit paměť pro řídicí blok a zdroje a tím snižuje nároky na konstrukci.Pokud nepoužíváte make_shared, pak budete muset použít explicitní nový výraz k vytvoření objektu před předejte jej shared_ptr konstruktor.Následující příklad ukazuje různé způsoby, jak deklarovat a inicializovat shared_ptr nového objektu.
// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
// Ok, but slightly less efficient.
// Note: Using new expression as constructor argument
// creates no named variable for other code to access.
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));
// When initialization must be separate from declaration, e.g. class members,
// initialize with nullptr to make your programming intent explicit.
shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");
Následující příklad ukazuje, jak deklarovat a inicializovat shared_ptr instance, které převezmou sdílené vlastnictví objektu, který již byly přiděleny jiným shared_ptr.Předpokládejme, že sp2 je inicializována shared_ptr.
//Initialize with copy constructor. Increments ref count.
auto sp3(sp2);
//Initialize via assignment. Increments ref count.
auto sp4 = sp2;
//Initialize with nullptr. sp7 is empty.
shared_ptr<Song> sp7(nullptr);
// Initialize with another shared_ptr. sp1 and sp2
// swap pointers as well as ref counts.
sp1.swap(sp2);
shared_ptrje také užitečné pro kontejnery knihovny STL (Standard Template) při použití algoritmů, které kopírovat prvky.Můžete zabalit prvky shared_ptra zkopírujte jej do jiné nádoby s vědomím, že základní paměť je platné tak dlouho, dokud ji potřebujete a nesmí být delší.Následující příklad ukazuje, jak použít replace_copy_if algoritmus na shared_ptr instance ve vektoru.
vector<shared_ptr<Song>> v;
v.push_back(make_shared<Song>(L"Bob Dylan", L"The Times They Are A Changing"));
v.push_back(make_shared<Song>(L"Aretha Franklin", L"Bridge Over Troubled Water"));
v.push_back(make_shared<Song>(L"Thal�a", L"Entre El Mar y Una Estrella"));
vector<shared_ptr<Song>> v2;
remove_copy_if(v.begin(), v.end(), back_inserter(v2), [] (shared_ptr<Song> s)
{
return s->artist.compare(L"Bob Dylan") == 0;
});
for_each(v2.begin(), v2.end(), [] (shared_ptr<Song> s)
{
wcout << s->artist << L":" << s->title << endl;
});
You can use dynamic_pointer_cast, static_pointer_cast, and const_pointer_cast to cast a shared_ptr.Tyto funkce vypadat dynamic_cast, static_cast, a const_cast operátory.Následující příklad ukazuje, jak otestovat odvozený typ každý prvek vektoru z shared_ptr ze základní třídy, kopírovat prvky a zobrazit informace o nich.
vector<shared_ptr<MediaAsset>> assets;
assets.push_back(shared_ptr<Song>(new Song(L"Himesh Reshammiya", L"Tera Surroor")));
assets.push_back(shared_ptr<Song>(new Song(L"Penaz Masani", L"Tu Dil De De")));
assets.push_back(shared_ptr<Photo>(new Photo(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft.")));
vector<shared_ptr<MediaAsset>> photos;
copy_if(assets.begin(), assets.end(), back_inserter(photos), [] (shared_ptr<MediaAsset> p) -> bool
{
// Use dynamic_pointer_cast to test whether
// element is a shared_ptr<Photo>.
shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p);
return temp.get() != nullptr;
});
for_each(photos.begin(), photos.end(), [] (shared_ptr<MediaAsset> p)
{
// We know that the photos vector contains only
// shared_ptr<Photo> objects, so use static_cast.
wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location_ << endl;
});
Můžete předat shared_ptr jiné funkci následujícími způsoby:
Předat shared_ptr hodnotou.To vyvolá konstruktor kopie zvýší počet odkazů a vytvoří volaný vlastníka.Je malé množství režie v této operace, které mohou být významné v závislosti na tom, kolik shared_ptr objekty, které jsou předány.Tuto možnost použijte, když mezi volající a volaný kód smlouvy (implicitní nebo explicitní) vyžaduje, aby volaný vlastníka.
Předat shared_ptr odkaz nebo odkaz na const.V tomto případě není zvýšen počet odkazů a volaný přístup ukazatel tak dlouho, dokud volající nepřekračuje mimo rozsah.Nebo může rozhodnout, zda volaný vytvořit shared_ptr založené na odkazu a tím se stávají sdílené vlastníka.Tuto možnost použijte, pokud volající nemá žádný volaný nebo musí projít shared_ptr a chcete se vyhnout operaci kopírování z důvodů zlepšení výkonu.
Předáte základní ukazatel nebo odkaz na základní objekt.To umožňuje volaný použití objektu, ale neumožňuje vlastnictví akcií nebo prodloužit životnost.Pokud volaný vytvoří shared_ptr z raw ukazatel nové shared_ptr je nezávislý od originálu a nemá vliv na podkladové zdroje.Tuto možnost použijte v případě, že smlouva mezi volající a volaný jasně Určuje, že volající zachová vlastnictví shared_ptr životnost.
Jsou při rozhodování jak předat shared_ptr, zjistit, zda volaný má sdílení vlastnictví základních prostředků."Vlastník" je objekt nebo funkce, která lze zachovat základní prostředek alive pro tak dlouho, dokud jej potřebuje.Pokud volající má zaručit, že volaný můžete prodloužit životnost ukazatel nad jeho životnost (funkce), možnost použít první.V případě, že není důležité, zda volaný prodlouží dobu života, předat podle odkazu a nechat volaný, kopírovat, či nikoli.
Pokud budete muset není nutné udělit přístup k pomocné funkce základní ukazatele, a vědět, podpůrná funkce bude pouze pomocí ukazatele a vrátit před volání funkce vrátí, pak tuto funkci sdílení vlastnictví základní ukazatele.Právě má přístup k ukazatel během životnosti volajícího shared_ptr.V tomto případě je bezpečné předat shared_ptr referenční nebo průchod raw ukazatel nebo odkaz na odpovídající objekt.Tímto způsobem poskytuje výhodu malého výkonu a také vám mohou pomoci express programovací záměr.
Někdy, například v std:vector<shared_ptr<T>>, budete pravděpodobně muset projít každý shared_ptr lambda výraz subjektu nebo pojmenovanou funkci objektu.Pokud lambda nebo funkce není ukládání ukazatel, potom předat shared_ptr ve vztahu k zamezení volání kopie konstruktoru pro každý element.
Následující příklad ukazuje jak shared_ptr přetížení různých relační operátory, aby ukazatel na paměti, která je vlastněna shared_ptr instance.
// Initialize two separate raw pointers.
// Note that they contain the same values.
auto song1 = new Song(L"Village People", L"YMCA");
auto song2 = new Song(L"Village People", L"YMCA");
// Create two unrelated shared_ptrs.
shared_ptr<Song> p1(song1);
shared_ptr<Song> p2(song2);
// Unrelated shared_ptrs are never equal.
wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl;
wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl;
// Related shared_ptr instances are always equal.
shared_ptr<Song> p3(p2);
wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl;
Viz také
Koncepty
Inteligentní ukazatelů (Příručka programování moderních C++)