Middle
Kuidas töötab std::shared_ptr viidete loendur?
sobes.tech AI
Vastus AI-lt
std::shared_ptr viitearv loetakse eraldi objektis — juhtimisblokis (control block).
See juhtimisblokk luuakse:
- Esimese
std::shared_ptrloomisel viitest. - Kasutaja määratud kustutaja või allocatoriga
std::shared_ptrloomisel. - Kasutades
std::make_sharedvõistd::allocate_shared.
See juhtimisblokk sisaldab vähemalt kahte loendurit:
- Tugevate viidete loendur (strong count): suureneb
std::shared_ptrloomisel või kopeerimisel, väheneb hävitamisel. Kui see loendur jõuab nulli, vabastatakse hallatav objekt. - Nõrkade viidete loendur (weak count): suureneb
std::weak_ptrloomiselstd::shared_ptr-st, väheneb hävitamisel. Juhtimisblokk vabastatakse, kui mõlemad loendurid — tugev ja nõrk — jõuavad nulli.
std::make_shared kasutamine on eelistatud otse new-i kasutamise ees, kuna see võib eraldada objekti ja juhtimisbloki ühes mälupunktis, parandades jõudlust ja vähendades fragmentatsiooni.
Aatomilised loendurid tagavad std::shared_ptr kasutamise ohutuse mitme niidi (multithreaded) stsenaariumites, kuigi hallatava objekti juurdepääs ei ole vaikimisi sünkroniseeritud.
Näide:
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") loodud\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") hävitatud\n";
}
};
int main() {
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
// tugev loendur: 1, nõrk loendur: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// tugev loendur: 2, nõrk loendur: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// tugev loendur: 2, nõrk loendur: 1
if (auto locked_ptr = weak_ptr.lock()) {
// tugev loendur: 3, nõrk loendur: 1 (lock ajal)
std::cout << "Objekti andmed: " << locked_ptr->data << std::endl;
}
// tugev loendur: 2, nõrk loendur: 1
} // ptr2 väljub ulatusest
// tugev loendur: 1, nõrk loendur: 1
// Objekt pole veel hävitatud, kuna tugev loendur on 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// tugev loendur: 1, nõrk loendur: 2
} // weak_ptr2 väljub ulatusest
// tugev loendur: 1, nõrk loendur: 1
} // ptr1 väljub ulatusest
// tugev loendur: 0, nõrk loendur: 1
// Objekt hävib, kuna tugev loendur sai 0
// Juhtimisblokk jääb alles kuni nõrk loendur jõuab 0-ni