Sobes.tech
Middle

Πώς λειτουργεί το shared_ptr στην C++;

sobes.tech AI

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

shared_ptr — είναι ένας έξυπνος δείκτης που υλοποιεί την σημασιολογία ιδιοκτησίας ενός κοινόχρηστου πόρου. Αποθηκεύει έναν δείκτη στο αντικείμενο και έναν δείκτη στο μπλοκ ελέγχου.

Το μπλοκ ελέγχου περιέχει:

  • Μετρητή ισχυρών αναφορών (reference count).
  • Μετρητή αδύναμων αναφορών (weak count).
  • Προσαρμοσμένο functor διαγραφής (deleter), αν οριστεί.
  • Προσαρμοστικό allocator, αν οριστεί.
  • Δείκτη στο αποθηκευμένο αντικείμενο (το ίδιο με αυτό που αποθηκεύεται στο shared_ptr).

Αρχή λειτουργίας:

  1. Δημιουργία: Κατά τη δημιουργία του πρώτου shared_ptr που δείχνει σε ένα αντικείμενο, δημιουργείται το μπλοκ ελέγχου και αρχικοποιούνται οι μετρητές αναφορών: ισχυροί — 1, αδύναμοι — 0.
    std::shared_ptr<int> ptr1 = std::make_shared<int>(10); // Δημιουργεί ένα αντικείμενο int και ένα μπλοκ ελέγχου
    
  2. Αντιγραφή: Κατά την αντιγραφή ενός shared_ptr, ο μετρητής ισχυρών αναφορών στο μπλοκ ελέγχου αυξάνεται κατά 1.
    std::shared_ptr<int> ptr2 = ptr1; // Αυξάνει τον μετρητή ισχυρών αναφορών
    
  3. Ανάθεση: Κατά την ανάθεση ενός shared_ptr, η παλιά πόρος μειώνεται (ο μετρητής ισχυρών αναφορών μειώνεται), και ο νέος πόρος αυξάνεται (αυξάνεται).
    std::shared_ptr<int> ptr3;
    ptr3 = ptr1; // Μειώνει τον παλιό πόρο του ptr3, αυξάνει τον πόρο του ptr1
    
  4. Διαγραφή: Κατά την καταστροφή ενός shared_ptr (π.χ., έξοδος από το scope), ο μετρητής ισχυρών αναφορών μειώνεται.
    {
        std::shared_ptr<int> ptr4 = ptr1; // Αυξάνει τον μετρητή ισχυρών αναφορών
        // το ptr4 βγαίνει από το scope
    } // Μειώνει τον μετρητή ισχυρών αναφορών
    
  5. Απελευθέρωση του πόρου: Όταν ο μετρητής ισχυρών αναφορών φτάσει στο μηδέν, ο πόρος (το αντικείμενο που δείχνει το shared_ptr) διαγράφεται χρησιμοποιώντας το καθορισμένο functor διαγραφής (ή delete κατά προεπιλογή).
  6. Απελευθέρωση του μπλοκ ελέγχου: Το μπλοκ ελέγχου απελευθερώνεται όταν και οι δύο μετρητές (ισχυρός και αδύναμος) φτάσουν στο μηδέν.

Πλεονεκτήματα:

  • Αυτόματη διαχείριση μνήμης για κοινόχρηστους πόρους.
  • Ασφάλεια από διπλή απελευθέρωση.
  • Υποστήριξη για προσαρμοσμένους functors διαγραφής.

Μειονεκτήματα:

  • Οι κυκλικοί σύνδεσμοι μπορούν να οδηγήσουν σε διαρροές μνήμης (weak_ptr).
  • Μικρή αύξηση κόστους λόγω του μπλοκ ελέγχου και των ατομικών λειτουργιών στους μετρητές.
  • Ασφάλεια στις λειτουργίες με το ίδιο shared_ptr (αντιγραφή, ανάθεση, αλλαγή δείκτη), αλλά όχι με το αντικείμενο στο οποίο δείχνει.