2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Raaka-osoittimien haitat:
delete
Vapauta resurssit aiheuttaen resurssivuotojadelete
Ohjelma poistui normaalisti ennen (esimif
keskelläreturn
) tai poistu epätavallisesti ennen kuin on liian myöhäistädelete
, mikä johtaa resurssien vuotamiseenTällä hetkellä tarvitaan älykkäitä vihjeitä. Älykkäiden osoittimien älykkyys näkyy pääasiassa siinä, että käyttäjien ei tarvitse kiinnittää huomiota resurssien vapauttamiseen, koska älykkäät osoittimet auttavat hallitsemaan resurssien vapauttamista täysin. Se varmistaa, että ohjelman logiikka toimii riippumatta , se suoritetaan normaalisti tai luo poikkeuksia.Kun resurssit vanhenevat (toiminnon laajuus tai ohjelma loppuu), ne vapautetaan.
Toteutetaan yksinkertainen älykäs osoitin itse
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T* ptr = nullptr) : mptr(ptr) {}
~CSmartPtr() { delete mptr; }
private:
T* mptr;
};
int main()
{
CSmartPtr<int> ptr(new int());
/*其它的代码...*/
/*
由于ptr是栈上的智能指针对象,不管是函数正常执行完,
还是运行过程中出现异常,栈上的对象都会自动调用析构函数,
在析构函数中进行了delete操作,保证释放资源
*/
return 0;
}
Siksi edellä mainituista ominaisuuksista johtuen älykkäät osoittimet määritellään yleensä pinossa. samaan aikaan,Älykäs osoitin on luokkaobjekti , osoitin välitetään tämän luokan konstruktorissa ja hyväksytty osoitin vapautetaan destruktorissa.Koska tämän tyyppinen objekti varataan ja vapautetaan pinosta, se vapautetaan automaattisesti, kun toimintomme (tai ohjelmamme) päättyy.
Joten voidaanko älykkäitä osoittimia määrittää kasaan?esimerkiksiCSmartPtr* p = new CSmartPtr(new int);
, kokoelma voi kulkea, mutta määritelmä täälläp
Vaikka se on älykäs osoitintyyppi, se on pohjimmiltaan raakaosoitinp
Se on silti tehtävä manuaalisestidelete
, se on palannut ongelmaan, jonka kohtasimme alussa paljailla osoittimilla, joten älä käytä sitä näin
Tietysti älykkäiden osoittimien tulee olla samanlaisia kuin raakaosoittimia, ja niissä on myös oltava raakaosoittimien yhteisiä ominaisuuksia.*
ja->
Kahden operaattorin ylikuormitetut toiminnot ovat todella samoja kuin raakaosoittimet, kun niitä käytetään.
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T* ptr = nullptr) : mptr(ptr) {}
~CSmartPtr() { delete mptr; }
T& operator*() { return *mptr; }
T* operator->() { return mptr; }
private:
T* mptr;
};
int main()
{
CSmartPtr<int> ptr(new int());
*ptr = 20; // operator*()一定要返回引用,这样才可以赋值
cout << *ptr << endl; // 20
class Test
{
public:
void test() { cout << "call Test::test()" << endl; }
};
CSmartPtr<Test> ptr2 = new Test();
(*ptr2).test(); // (*ptr2)取出Test对象,用对象调用方法
// operator->()返回的是一个指针,实现了用指针调用函数
// 即(ptr2.operator->()) -> test()
ptr2->test();
return 0;
}
Edellisessä osiossa toteutettu älykäs osoitin on hyvin samanlainen kuin tavallinen käytössä oleva raakaosoitin, mutta siinä on silti suuria ongelmia. Katso seuraava koodi:
CSmartPtr<int> p1(new int());
CSmartPtr<int> p2(p1); // 拷贝构造
Käynnissä oleva koodi kaatuu suoraan, koska oletuskopion rakentaja tekee matalan kopion.p1
jap2
pitää samaanew int
resurssi,p2
Tuhoaminen vapauttaa ensin resurssit, sittenp1
Kun tuhoutuu, siitä tuleedelete
Villi osoitin, ohjelma kaatuu
Joten kuinka ratkaista pinnallisen kopioinnin aiheuttamat ongelmat?kirjoittaa uudelleenCSmartPtr
Katso kopiokonstruktori
CSmartPtr(const CSmartPtr<T>& src) { mptr = new T(*src.mptr); }
Nyt koodi toimii kuitenkin normaalisti tässä vaiheessap1
jap2
Hallitaan kahta eri resurssia, jos käyttäjät eivät ymmärrä niitä, he luulevat virheellisesti niinp1
jap2
Hallinnoi samaa resurssia
Siksi on väärin kirjoittaa kopiokonstruktori tällä tavalla
Joten kuinka ratkaista älykkäiden osoittimien matala kopioongelma? Kaksi tapaa:Älykkäät osoittimet ilman viitelaskentaa, älykkäät osoittimet viitelaskennan kanssa
Katsotaanpa ensin tämä osioÄlykkäät osoittimet ilman viitteiden laskemista
auto_ptr
(C++98, nyt vanhentunut)scoped_ptr
(Boost kirjasto)unique_ptr
(C++11, suositeltava)Sisällytä otsikkotiedosto, kun käytät:#include <memory>
Mietitäänpä tätä koodia ensin
auto_ptr<int> ptr1(new int());
auto_ptr<int> ptr2(ptr1);
*ptr2 = 20;
cout << *ptr1 << endl;
Operaatio kaatui.auto_ptr
lähdekoodi
Voit nähdä, että kopiorakenne soittaa saapuvalle objektillerelease
menetelmä, tämä menetelmä on laittaa_Right
Osoitettu resurssi palautetaan uuteenauto_ptr
kohde, ja samalla_Right
(vanhaauto_ptr
)/_Myptr
asetettunullptr
Lyhyesti sanottuna se on laittaa vanhaauto_ptr
Osoitettu resurssi annetaan uudelleauto_ptr
Pidetty, vanha on asetettunullptr
.Siksi yllä oleva koodi käyttää*ptr1
Vain väärin.(auto_ptr
Anna aina viimeisen älykäs osoittimen hallita resurssia)
Niin,auto_ptr
Voidaanko sitä käyttää säiliössä. Katso seuraava koodi.
int main()
{
vector<auto_ptr<int>> vec;
vec.push_back(auto_ptr<int>(new int(10)));
vec.push_back(auto_ptr<int>(new int(20)));
vec.push_back(auto_ptr<int>(new int(30)));
cout << *vec[0] << endl; // 10
vector<auto_ptr<int>> vec2 = vec;
/* 这里由于上面做了vector容器的拷贝,
相当于容器中的每一个元素都进行了拷贝构造,
原来vec中的智能指针全部为nullptr了,
再次访问就成访问空指针了,程序崩溃
*/
cout << *vec[0] << endl; // 程序崩溃
return 0;
}
Siksi se on vanhentunut C++:ssaauto_ptr
, ellei sovellusskenaario ole hyvin yksinkertainen.jaauto_ptr
Vanhentunut C++11:ssä ja poistettu kokonaan C++17:stä
Yhteenveto:auto_ptr
Älykkäissä osoittimissa ei ole viitelaskentaa, joten ne ratkaisevat matalan kopioinnin ongelman kopioimalla suoraan edellisenauto_ptr
on asetettunullptr
, olkoon vain viimeinenauto_ptr
pitää resursseja
Sinun on asennettava Boost-kirjasto, joka sisältää otsikkotiedostot.#include <boost/scoped_ptr.hpp>
Valmis käytettäväksi
Katsoscoped_ptr
Lähdekoodi:
template<class T> class scoped_ptr
{
private:
scoped_ptr(scoped_ptr const&);
scoped_ptr& operator=(scoped_ptr const&);
...
};
voidaan nähdäscoped_ptr
Kopioiden rakentaja ja määritystoiminto ovat molemmat yksityistetty, joten objekti ei tue näitä kahta toimintoa eikä sitä voida kutsua, mikä estää pohjimmiltaan matalien kopioiden esiintymisen.
niinscoped_ptr
Sitä ei voi käyttää säilöissä, jos säiliöt kopioivat tai määrittävät arvoja toisilleenscoped_ptr
Objektikopion rakentaja ja osoitusfunktio, käännösvirhe
scoped_ptr
jaauto_ptr
Ero: Voidaan selittää omistajuudella,auto_ptr
Resurssien omistusoikeus voidaan siirtää haluttaessascoped_ptr
Omistajuutta ei siirretä (koska kopiointikonstruktorit ja määritystoiminnot on poistettu käytöstä)
scoped_ptr
Yleensä ei käytetä
Katso ensinunique_ptr
Osa lähdekoodia:
template<class _Ty, class _Dx>
class unique_ptr
{
public:
/*提供了右值引用的拷贝构造函数*/
unique_ptr(unique_ptr&& _Right) { ... }
/*提供了右值引用的operator=赋值重载函数*/
unique_ptr& operator=(unique_ptr&& _Right) { ... }
/*
删除了unique_ptr的拷贝构造和赋值函数,
因此不能做unique_ptr智能指针对象的拷贝构造和赋值,
防止浅拷贝的发生
*/
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
};
Ylhäältä katsottuna,unique_ptr
hiemanscoped_ptr
Samoin tehdään, eli kopioinnin rakentaminen ja osoitus ylikuormitetut toiminnot poistetaan käytöstä ja käyttäjiä ei saa käyttääunique_ptr
Suorita eksplisiittinen kopion rakentaminen ja määrittäminen estääksesi älykäs osoittimen matalia kopiointiongelmia.
Koska kopiokonstruktoria ei ole,unique_ptr<int> p1(new int()); unique_ptr<int> p2(p1);
Luonnollisesti se on väärin
muttaunique_ptr
Tarjoaa kopiointikonstruktorit ja osoitusfunktiot rvalue-viittausparametreilla, eliunique_ptr
Älykkäät osoittimet voivat suorittaa kopiointi- ja määritystoimintoja rarvoviittausten kautta tai luodaunique_ptr
Paikka väliaikaisille esineille, esimunique_ptr
Toiminnon palautusarvona esimerkkikoodi on seuraava:
// 示例1
unique_ptr<int> p1(new int());
unique_ptr<int> p2(move(p1)); // 使用了右值引用的拷贝构造
p2 = move(p1); // 使用了右值引用的operator=赋值重载函数
// 示例2
unique_ptr<int> test_uniqueptr()
{
unique_ptr<int> ptr(new int());
return ptr;
}
int main()
{
/*
此处调用test_uniqueptr函数,在return ptr代码处,
调用右值引用的拷贝构造和赋值函数
*/
unique_ptr<int> p = test_uniqueptr(); // 调用带右值引用的拷贝构造函数
p = test_uniqueptr(); // 调用带右值引用的operator=赋值重载函数
return 0;
}
Käytä sittenunique_ptr
Etuna on, että käyttäjät voivat käyttää jotain vastaavaaunique_ptr<int> p2(move(p1));
lausunto, sen voi selvästi nähdäp1
Resurssit siirretty osoitteeseenp2
,p1
Enempää resursseja ei säilytetä, jos käytätauto_ptr
Se ei tule olemaan nimenomaisestimove
Kirjoitettu, tarkoitus ei ole ilmeinen, jos et ymmärrä alla olevaa kerrosta, käytät sitä väärin.
Samaan aikaan alkaenunique_ptr
Kuten nimestä näkyy, resurssiin viittaava älykäs osoitin voi olla lopussa. Siksi on suositeltavaa antaa etusijalle älykäs osoitin ilman viitelaskentaa.unique_ptr
Älykkäät osoittimet viitelaskentaan sisältävät pääasiassashared_ptr
jaweak_ptr
, viitelaskentaanhyötyäToisin sanoen useat älykkäät osoittimet voivat hallita samaa resurssia.
Viitelaskennan kanssa: Yhdistä kunkin objektin resurssin viitemäärä.
Kun useiden älykkäiden osoittimien sallitaan osoittaa samaan resurssiin, jokainen älykäs osoitin lisää 1:n resurssin viitemäärään. Viimeinen älykäs osoitin Kun resurssin viitemäärä laskee 1:stä nollaan, se tarkoittaa, että resurssi voidaan vapauttaa Viimeisen älykäs osoittimen tuhoaja käsittelee resurssin vapauttamisen.
Ota se, mikä on toteutettu aiemminCSmartPtr
Tee muutokset ja lataa koodi suoraan:
// 对资源进行引用计数的类
template<typename T>
class RefCnt
{
public:
RefCnt(T* ptr = nullptr) : mptr(ptr)
{
if (mptr != nullptr)
mcount = 1;
}
void addRef() { mcount++; } // 增加资源的引用计数
int delRef() { return --mcount; }
private:
T* mptr;
int mcount;
};
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T* ptr = nullptr) : mptr(ptr)
{
// 智能指针构造的时候给资源建立引用计数对象
mpRefCnt = new RefCnt<T>(mptr);
}
~CSmartPtr()
{
if (0 == mpRefCnt->delRef())
{
delete mptr;
mptr = nullptr;
}
}
// 实现拷贝构造
CSmartPtr(const CSmartPtr<T>& src)
:mptr(src.mptr), mpRefCnt(src.mpRefCnt)
{
if (mptr != nullptr)
mpRefCnt->addRef();
}
CSmartPtr<T>& operator=(const CSmartPtr<T>& src)
{
// 防止自赋值
if (this == &src)
return *this;
// 本身指向的资源减1
// 如果减1为0释放资源;如果减1不为0直接走
if (0 == mpRefCnt->delRef()) { delete mptr; }
mptr = src.mptr;
mpRefCnt = src.mpRefCnt;
mpRefCnt->addRef();
return *this;
}
T& operator*() { return *mptr; }
T* operator->() { return mptr; }
private:
T* mptr; // 指向资源的指针
RefCnt<T>* mpRefCnt; // 指向该资源引用计数对象的指针
};
// 那么现在就不会报错了,不会对同一个资源释放多次
CSmartPtr<int> ptr1(new int());
CSmartPtr<int> ptr2(ptr1);
CSmartPtr<int> ptr3;
ptr3 = ptr2;
*ptr1 = 20;
cout << *ptr2 << " " << *ptr3 << endl; // 20 20
Näin useat älykkäät osoittimet voivat hallita samaa resurssia.
Nyt käyttöönottamamme älykkäät osoittimet eivät kuitenkaan ole säikeen turvallisia, eikä niitä voida käyttää monisäikeisissä skenaarioissa.Toteuttaja Curryshared_ptr
jaweak_ptr
Se on lankaturvallinen!
shared_ptr
:voimakasÄlykkäät osoittimet (voi muuttaa resurssien viitemäärää)weak_ptr
:heikkoÄlykkäät osoittimet (älä muuta resurssin viitemäärää)Mitä toteutimme edellisessä osiossaCSmartPtr
Myös vahva älykäs osoitin (voi muuttaa resurssin viitemäärää)
Sen voi ymmärtää näin: Heikko älykäs osoitin tarkkailla Vahvat älykkäät osoittimet Vahvat älykkäät osoittimettarkkailla Resurssit (muisti)
Niin,Vahva älykäs osoittimen ristiviittaus (ympyräviittaus) ongelma mitä se sitten on?Tule katsomaan
class B; // 前置声明类B
class A
{
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
shared_ptr<B> _ptrb; // 指向B对象的智能指针
};
class B
{
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
shared_ptr<A> _ptra; // 指向A对象的智能指针
};
int main()
{
shared_ptr<A> pa(new A()); // pa指向A对象,A的引用计数为1
shared_ptr<B> pb(new B()); // pb指向B对象,B的引用计数为1
pa->_ptrb = pb; // A对象的成员变量_ptrb也指向B对象,B的引用计数为2
pb->_ptra = pa; // B对象的成员变量_ptra也指向A对象,A的引用计数为2
cout << pa.use_count() << endl;
cout << pb.use_count() << endl;
return 0;
}
operaation tulos:
A()
B()
2
2
Kuten näet, A ja B eivät tuhoudu, mikä tarkoittaa, että ristiviittaukset aiheuttavatnew
Ulostulevia resursseja ei voida vapauttaa, mikä johtaa resurssien vuotamiseen!
analysoida:
ulosmain
toiminnon laajuus,pa
japb
Kaksi paikallista objektia tuhotaan ja objektin A ja B:n viitemäärät pienennetään 2:sta 1:een. A:n ja B:n vapauttamisen ehtoja ei voida täyttää (vapauttamisen ehto on, että A:n ja B:n viitemäärää pienennetään). 0), mikä aiheuttaa kaksinew
A- ja B-objekteja, jotka tulivat ulos, ei voida vapauttaa, mikä aiheuttaa muistivuotojaVahva älykäs osoittimen ristiviittaus (ympyräviittaus) ongelma
Ratkaisu: Käytä vahvoja älykkäitä osoittimia, kun määrität objekteja, ja käytä heikkoja älykkäitä osoittimia viitattaessasi objekteihin.
class B; // 前置声明类B
class A
{
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
weak_ptr<B> _ptrb; // 指向B对象的弱智能指针(引用对象时,用弱智能指针)
};
class B
{
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
weak_ptr<A> _ptra; // 指向A对象的弱智能指针(引用对象时,用弱智能指针)
};
int main()
{
// 定义对象时,用强智能指针
shared_ptr<A> pa(new A()); // pa指向A对象,A的引用计数为1
shared_ptr<B> pb(new B()); // pb指向B对象,B的引用计数为1
// A对象的成员变量_ptrb也指向B对象,B的引用计数为1,因为是弱智能指针,引用计数没有改变
pa->_ptrb = pb;
// B对象的成员变量_ptra也指向A对象,A的引用计数为1,因为是弱智能指针,引用计数没有改变
pb->_ptra = pa;
cout << pa.use_count() << endl; // 1
cout << pb.use_count() << endl; // 1
return 0;
}
operaation tulos:
A()
B()
1
1
~B()
~A()
voidaan nähdä, ulosmain
toiminnon laajuus,pa
japb
Kaksi paikallista objektia tuhotaan, ja objektin A ja objektin B vertailumäärät pienennetään 1:stä 0:aan saavuttaen ehdot A:n ja B:n vapauttamiselle.new
A-objekti ja B-objekti, jotka tulivat ulos, tuhoutuivat, mikä ratkaisi ongelman.Vahva älykäs osoittimen ristiviittaus (ympyräviittaus) ongelma
voidaan nähdä,weak_ptr
Heikko älykäs osoitin ei muuta resurssin viitemäärää, mikä tarkoittaa, että heikko älykäs osoitin vain tarkkailee, onko objekti elossa (onko viiteluku 0), eikä voi käyttää resurssia.
Sitten jos tällä kertaa, lisää luokkaan Avoid testA() { cout << "非常好用的方法!!" << endl; }
Tällainen menetelmä lisää B:tävoid func() { _ptra->testA(); }
Onko oikein kutsua tätä menetelmää?
*
ja->
Operaattoreiden ylikuormitetut toiminnot eivät voi käyttää raakaosoittimien kaltaisia toimintojaRatkaisu:
class B; // 前置声明类B
class A
{
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void testA() { cout << "非常好用的方法!!" << endl; }
weak_ptr<B> _ptrb; // 指向B对象的弱智能指针(引用对象时,用弱智能指针)
};
class B
{
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
void func()
{
shared_ptr<A> sp = _ptra.lock(); // 提升方法,出函数作用域就自动析构了
if (sp != nullptr)
sp->testA();
}
weak_ptr<A> _ptra; // 指向A对象的弱智能指针(引用对象时,用弱智能指针)
};
int main()
{
shared_ptr<A> pa(new A());
shared_ptr<B> pb(new B());
pa->_ptrb = pb;
pb->_ptra = pa;
cout << pa.use_count() << endl; // 1
cout << pb.use_count() << endl; // 1
pb->func();
return 0;
}
Siitä huolimatta
weak_ptr
ei omista esinettä, mutta se voi kulkealock()
menetelmä yrittää saada osoittimen objektiinshared_ptr
, jos esine on vielä elossa (eli muitashared_ptr
osoita sitä),lock()
palauttaa osoittimen objektiinshared_ptr
Muussa tapauksessa palautetaan tyhjä arvoshared_ptr
käyttää
lock()
Tyypillinen skenaario menetelmille on, kun tilapäinen pääsy vaaditaanweak_ptr
kohde osoitti, eivätkä samalla halua lisätä kohteen käyttöikää
operaation tulos:
A()
B()
1
1
非常好用的方法!!
~B()
~A()
Tässä vaiheessa näet, että sitä kutsuttiin oikein!
Katsotaanpa yksiSäikeen turvallisuusongelmat käytettäessä jaettuja objekteja useista säikeistä: Säie A ja säie B käyttävät jaettua objektia, jos säie A tuhoaa objektin, säie A on saattanut tuhota objektin, mutta säie B ei Jos yrität käyttää objektia, tapahtuu odottamaton virhe.
Katso ensin seuraava koodi:
class A
{
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void testA() { cout << "非常好用的方法!!" << endl; }
};
// 子线程
void handler01(A* q)
{
// 睡眠两秒,此时main主线程已经把A对象给delete析构掉了
std::this_thread::sleep_for(std::chrono::seconds(2));
q->testA();
}
// main线程
int main()
{
A* p = new A();
thread t1(handler01, p);
delete p;
//阻塞当前线程,直到调用join()的线程结束
t1.join();
return 0;
}
toteutuksessaq->testA();
Kun tämä lausunto annetaan,main
Säie on tuhonnut jaetun objektin, mikä on ilmeisen kohtuutonta.
Jos haluat ohittaaq
Jos osoitin haluaa käyttää A-objektia, sen on määritettävä, onko A-objekti elossa. Jos A-objekti on elossa, kutsutestA
Menetelmässä ei ole ongelmaa, jos A-objekti on tuhoutunuttestA
on ongelma!Tarkoittaenq
Kun käytät objektia A, sinun on havaittava, onko objekti A elossa. Kuinka ratkaista tämä ongelma Sinun on käytettävä vahvoja ja heikkoja älykkäitä viitteitä.
Katsotaanpa tätä koodia:
// 子线程
void handler01(weak_ptr<A> wp)
{
// 睡眠两秒
std::this_thread::sleep_for(std::chrono::seconds(2));
shared_ptr<A> sp = wp.lock();
if (sp != nullptr)
sp->testA();
else
cout << "A对象已经析构,不能再访问!" << endl;
}
// main线程
int main()
{
shared_ptr<A> p(new A());
thread t1(handler01, weak_ptr<A>(p));
t1.join();
return 0;
}
operaation tulos:
A()
非常好用的方法!!
~A()
Voit nähdä, että se on käynnissäsp->testA();
,koskamain
Lanka kutsuit1.join()
Menetelmä odottaa aliketjun päättymistä tällä hetkelläwp
kulkealock
Onnistuneesti ylennettysp
Muokkaa yllä olevaa koodia:
// 子线程
void handler01(weak_ptr<A> wp)
{
// 睡眠两秒
std::this_thread::sleep_for(std::chrono::seconds(2));
shared_ptr<A> sp = wp.lock();
if (sp != nullptr)
sp->testA();
else
cout << "A对象已经析构,不能再访问!" << endl;
}
// main线程
int main()
{
{
shared_ptr<A> p(new A());
thread t1(handler01, weak_ptr<A>(p));
t1.detach();
}
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}
operaation tulos:
A()
~A()
A对象已经析构,不能再访问!
Kuten näet, asetamme laajuuden ja myös asetimmet1
Erota viestiketjut käyttämällä älykkäitä osoittimiap
Kun A tuhotaan soveltamisalan ulkopuolella, se tulostetaan tällä hetkelläA对象已经析构,不能再访问!
, tuo onwp
kulkealock
Päivitys tiedostoon epäonnistuisp
Yllä oleva on säikeen turvallisuusongelma, kun useat säikeet käyttävät jaettuja objektejashared_ptr
jaweak_ptr
Tyypillinen sovellus.
Viiteartikkeli:C++-älyosoittimien syvällinen ymmärtäminen