Životnost objektu a správu prostředků (moderní C++)
Na rozdíl od spravované jazyků C++ nemá uvolněné (GC), který automaticky uvolní prostředky č delší používané paměti při spuštění programu.V jazyce C++ správy prostředků přímo souvisí s životnost objektu.Tento dokument popisuje faktory, které ovlivňují životnost objektu v C++ a jak ji spravovat.
C++ nemá GC, především proto, že je nelze zpracovat bez paměťové prostředky.Destruktory deterministický, stejně jako v C++ lze zpracovat pouze prostředky paměti a bez paměti stejně.GC má také další problémy, stejně jako vyšší nároky na paměť a spotřebu procesoru a lokality.Ale obecnosti je základní problém, který nelze Neimplementujte dokonalá optimalizace.
Koncepty
Důležité v řízení životnosti objektu je zapouzdření – hráč používá objekt nemá prostředky, které objekt vlastní nebo jak je zbavit nebo dokonce zda vlastní prostředky vůbec znát.Právě je zničení objektu.Základní jazyk C++ je určena k zajištění, že jsou objekty, zničeny ve správnou dobu, jako jsou ukončen bloky, v opačném pořadí v konstrukci.Po zničení objektu, jeho základny a členy zničeny v určitém pořadí.Jazyk automaticky ničí objekty, dokud neprovedete zvláštní například přidělení haldy nebo nové umístění.Například inteligentní ukazatele jako unique_ptr a shared_ptr, a jako kontejnery standardní šablonu knihovny (STL) vector, zapouzdření new/delete a new[]/delete[] v objektech, které mají destruktory.Proto je tak důležité používat inteligentní ukazatele a kontejnery STL.
Jiné důležité koncepce řízení životnosti: destruktory.Destruktory zapouzdřit uvolnění prostředků.(Běžně používaných symbol je RRID zničení je uvolnění prostředků). Prostředek je něco získat z "systém" a zadat později.Paměť je nejběžnější prostředek, ale existují také soubory, sokety, textury a jiné zdroje než paměti. "Vlastnící"zdroje znamená, že je můžete použít, když ji potřebujete, ale máte také jej uvolněte, až skončíte s ním.Po zničení objektu, jeho destruktoru uvolní prostředky, které jeho vlastnictví.
Závěrečný pojem je DAG (řízené Acyklické grafu).Struktura vlastnictví v programu formuláře DAG.Žádný objekt může vlastnit sebe sama – není pouze nemožné, ale také ze své podstaty bezvýznamnou.Ale dva objekty můžete sdílet vlastnictví třetí objekt.Několik druhů odkazy jsou možné v DAG takto: A je členem B (B vlastní A), C obchody vector<D> (C vlastní každý prvek D), E obchody shared_ptr<F> (E podíly vlastnictví F, případně s dalšími objekty), a tak dále.Neexistují žádné cykly a každý odkaz DAG je reprezentován objekt destructor (namísto raw ukazatel úchytu nebo jiným mechanismem), která má potom nedostatku prostředků jsou nemožné, protože jazyk zabrání jim.Prostředky jsou uvolněny ihned po jste již nepotřebujete, bez bez garbage collector systémem.Životnost sledování je bez režie pro obor zásobníku, základy, členy a související případy a levné pro shared_ptr.
Životnost založené haldy
Životnost objektu haldy pomocí inteligentní ukazatele.Použití shared_ptr a make_shared jako výchozí kurzor a přidělování.Použití weak_ptr cyklů přerušení, proveďte do mezipaměti a pozorovat objekty bez ovlivnění nebo za předpokladu, že nic o jejich životnosti.
void func() {
auto p = make_shared<widget>(); // no leak, and exception safe
...
p->draw();
} // no delete required, out-of-scope triggers smart pointer destructor
Použití unique_ptr pro jedinečné vlastnictví v například pimpl idiomu.(See Pimpl pro zapouzdření kompilace (moderní C++).) Aby unique_ptr primární cíl všechny explicitní new výrazy.
unique_ptr<widget> p(new widget());
Raw ukazatele můžete použít bez vlastnictví a pozorování.Ukazatel vlastnící může dangle, ale nelze nevrací.
class node {
...
vector<unique_ptr<node>> children; // node owns children
node* parent; // node observes parent, which is not a concern
...
};
node::node() : parent(...) { children.emplace_back(new node(...) ); }
Při optimalizaci výkonu je vyžadováno, bude pravděpodobně nutné použít well-encapsulated vlastnící ukazatele a explicitní volání odstranit.Je například při implementaci vlastní strukturu dat nižší úrovně.
Životnost založené na zásobníku
V jazyce C++ moderní oboru založené na zásobníku je efektivní způsob psaní kódu robustní, protože kombinuje automatické životnost zásobníku a životnost členských dat s vysokou účinností – sledování životnost je v podstatě bez režie.Životnost objektu haldy vyžaduje důslednost ruční řízení a může být zdrojem nedostatku prostředků a přebytku, zejména při práci s raw ukazatele.Zvažte tento kód ukazuje oboru založené na zásobníku:
class widget {
private:
gadget g; // lifetime automatically tied to enclosing object
public:
void draw();
};
void functionUsingWidget () {
widget w; // lifetime automatically tied to enclosing scope
// constructs w, including the w.g gadget member
…
w.draw();
…
} // automatic destruction and deallocation for w and w.g
// automatic exception safety,
// as if "finally { w.dispose(); w.g.dispose(); }"
Používejte opatrně statické životnost (statické globální, místní statické funkce) protože může dojít k problémům.Co se stane, když konstruktoru globální objekt výjimku?Obvykle app poruch tak, že může být obtížné ladit.Pořadí konstrukce je problematický statický životnosti objektů a není bezpečné souběžnosti.Problém, pouze je stavba objektu zničení objednávky může být složité, obzvláště pokud polymorfismus zapojen.I když objekt nebo proměnné není polymorfní a nemá složité konstrukce zničení objednávání, je stále problém souběžnosti podprocesu.Podprocesy aplikace nelze změnit bezpečně data statických objektů bez nutnosti podproces místní úložiště, uzamčení prostředků a jiná zvláštní opatření.