Middle
Ինչպես է աշխատում հղումների հաշվիչը std::shared_ptr-ում։
sobes.tech AI
Պատասխան AI-ից
std::shared_ptr-ի հղումների հաշվիչը պահվում է առանձին օբյեկտում՝ կառավարման բլոկում (control block):
Կառավարման բլոկը ստեղծվում է՝
- Երբ առաջին անգամ
std::shared_ptr-ը ստեղծվում է ցուցիչից: - Երբ
std::shared_ptr-ը ստեղծվում է օգտագործողի կողմից սահմանված մաքրման գործառական կամ ալոկատորով: - Երբ օգտագործվում է
std::make_sharedկամstd::allocate_shared:
Այս կառավարման բլոկը պարունակում է առնվազն երկու հաշվիչ՝
- Համառկած հղումների հաշվիչ (strong count): Հավելվում է
std::shared_ptr-ի ստեղծման կամ պատճենահանման ժամանակ, նվազում՝ այն ոչնչացնելիս: Երբ այս հաշվիչը դառնում է զրո, կառավարելի օբյեկտը ազատվում է: - Ազատ հղումների հաշվիչ (weak count): Հավելվում է
std::weak_ptr-ի ստեղծման ժամանակ, նվազում՝ այն ոչնչացնելիս: Կառավարման բլոկը ազատվում է, երբ երկու հաշվիչներն էլ՝ ուժեղ և թույլ, դառնում են զրո:
std::make_shared-ի օգտագործումը նախընտրելի է ուղղակի new-ից ստեղծելու փոխարեն, քանի որ այն կարող է միաժամանակ ալոկատել օբյեկտը և կառավարման բլոկը՝ մեկ հիշողության բլոկում, ինչը բարելավում է կատարողականությունը և նվազեցնում ֆրագմենտացիան:
Ատոմիկ հաշվիչները ապահովում են std::shared_ptr-ի անվտանգությունը բազմաթ/thread-ային միջավայրում, չնայած կառավարվող օբյեկտի մուտք գործելը ըստ նախնական կարգավորումների չի սինխրոնիզացված:
Օրինակ՝
#include <iostream>
#include <memory>
struct MyObject {
int data;
MyObject(int d) : data(d) {
std::cout << "MyObject(" << data << ") ստեղծվեց\n";
}
~MyObject() {
std::cout << "MyObject(" << data << ") ոչնչացվեց\n";
}
};
int main() {
std::shared_ptr<MyObject> ptr1 = std::make_shared<MyObject>(10);
// ուժեղ հաշվիչ: 1, թույլ հաշվիչ: 0
{
std::shared_ptr<MyObject> ptr2 = ptr1;
// ուժեղ հաշվիչ: 2, թույլ հաշվիչ: 0
std::weak_ptr<MyObject> weak_ptr = ptr1;
// ուժեղ հաշվիչ: 2, թույլ հաշվիչ: 1
if (auto locked_ptr = weak_ptr.lock()) {
// ուժեղ հաշվիչ: 3, թույլ հաշվիչ: 1 (lock-ի ներսում)
std::cout << "Объект տվյալները: " << locked_ptr->data << std::endl;
}
// ուժեղ հաշվիչ: 2, թույլ հաշվիչ: 1
} // ptr2 դուրս է գալիս տարածքից
// ուժեղ հաշվիչ: 1, թույլ հաշվիչ: 1
// Օբյեկտը դեռ չի ոչնչացվել, քանի որ ուժեղ հաշվիչը == 1
{
std::weak_ptr<MyObject> weak_ptr2 = ptr1;
// ուժեղ հաշվիչ: 1, թույլ հաշվիչ: 2
} // weak_ptr2 դուրս է գալիս տարածքից
// ուժեղ հաշվիչ: 1, թույլ հաշվիչ: 1
} // ptr1 դուրս է գալիս տարածքից
// ուժեղ հաշվիչ: 0, թույլ հաշվիչ: 1
// Օբյեկտը ոչնչացվում է, քանի որ ուժեղ հաշվիչը դարձել է 0
// Կառավարման բլոկը մնում է մինչև թույլ հաշվիչը չդառնա 0