Sobes.tech
Middle

Με ποια βάση μπορούν πολλά αντικείμενα shared_ptr να αναφέρονται στην ίδια δείκτη;

sobes.tech AI

Απάντηση από AI

Πολλά αντικείμενα std::shared_ptr μπορούν να αναφέρονται στην ίδια δείκτη χάρη στην ύπαρξη ενός control block (control block).

Το control block που σχετίζεται με το διαχειριζόμενο αντικείμενο περιέχει:

  • Μετρητή ισχυρών αναφορών (strong reference count): Αυξάνεται κατά τη δημιουργία ενός νέου shared_ptr για το ίδιο αντικείμενο. Μειώνεται κατά την καταστροφή ενός shared_ptr. Όταν φτάσει το μηδέν, το συσχετιζόμενο αντικείμενο (δείκτης) διαγράφεται.
  • Μετρητή αδύναμων αναφορών (weak reference count): Χρησιμοποιείται για std::weak_ptr. Αυξάνεται κατά τη δημιουργία ενός weak_ptr από ένα shared_ptr. Μειώνεται κατά την καταστροφή ενός weak_ptr. Όταν και οι δύο μετρητές φτάσουν το μηδέν, το control block διαγράφεται.
  • Ιδιωτικός δείκτης στο διαχειριζόμενο αντικείμενο: Όχι ο δείκτης δεδομένων, αλλά αυτός που διαχειρίζεται το control block.

Όταν δημιουργείτε ένα shared_ptr από ένα υπάρχον shared_ptr (αντιγραφή, ανάθεση-αντιγραφή), και οι δύο αρχίζουν να χρησιμοποιούν το ίδιο control block, και ο μετρητής ισχυρών αναφορών σε αυτό το block αυξάνεται.

Παράδειγμα:

#include <memory>
#include <iostream>

struct MyData {
    int value;
    MyData(int v) : value(v) { std::cout << "MyData(" << value << ") created.\n"; }
    ~MyData() { std::cout << "MyData(" << value << ") destroyed.\n"; }
};

int main() {
    // Δημιουργείται το πρώτο shared_ptr.
    // Δημιουργείται το control block και το αντικείμενο MyData.
    // Μετρητές: ισχυρός: 1, αδύναμος: 0.
    std::shared_ptr<MyData> ptr1 = std::make_shared<MyData>(10);
    std::cout << "μετρητής χρήσης ptr1: " << ptr1.use_count() << "\n";

    // Δημιουργείται ένα δεύτερο shared_ptr από το ptr1.
    // Χρησιμοποιεί το ίδιο control block.
    // Ο μετρητής ισχυρών αυξάνεται σε 2.
    std::shared_ptr<MyData> ptr2 = ptr1;
    std::cout << "μετρητής χρήσης ptr1: " << ptr1.use_count() << "\n";
    std::cout << "μετρητής χρήσης ptr2: " << ptr2.use_count() << "\n";

    // Δημιουργείται ένα τρίτο shared_ptr από το ptr1.
    // Χρησιμοποιεί το ίδιο control block.
    // Ο μετρητής ισχυρών αυξάνεται σε 3.
    std::shared_ptr<MyData> ptr3 = ptr1;
     std::cout << "μετρητής χρήσης ptr1: " << ptr1.use_count() << "\n";
    std::cout << "μετρητής χρήσης ptr2: " << ptr2.use_count() << "\n";
    std::cout << "μετρητής χρήσης ptr3: " << ptr3.use_count() << "\n";

    std::cout << "Έξοδος από το scope.\n";
    // ptr3 βγαίνει από το scope.
    // Ο μετρητής ισχυρών μειώνεται σε 2.
    // ptr2 βγαίνει από το scope.
    // Ο μετρητής ισχυρών μειώνεται σε 1.
    // ptr1 βγαίνει από το scope.
    // Ο μετρητής ισχυρών μειώνεται σε 0.
    // Το αντικείμενο MyData διαγράφεται.
    // Το control block διαγράφεται.
}

Κάθε αντικείμενο shared_ptr περιέχει τον δικό του δείκτη στο control block και τον δικό του δείκτη στο αντικείμενο δεδομένων. Κατά την αντιγραφή ενός shared_ptr, αντιγράφονται και οι δύο δείκτες, και ο μετρητής ισχυρών αναφορών στο κοινό control block αυξάνεται. Με αυτόν τον τρόπο, όλα τα shared_ptr δείχνουν στο ίδιο control block, το οποίο παρακολουθεί τον αριθμό των αντιγράφων που κατέχουν τον πόρο και καθορίζει τη στιγμή καταστροφής του διαχειριζόμενου πόρου.