Sobes.tech
Middle

Τι γνωρίζετε για τους έξυπνους δείκτες σε C++;

sobes.tech AI

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

Έξυπνοι δείκτες - είναι RAII-επεκτάσεις πάνω από τους συνηθισμένους (ωμούς) δείκτες στη C++, που παρέχουν αυτόματο έλεγχο του χρόνου ζωής της κατανεμημένης μνήμης, αποτρέποντας διαρροές.

Οι βασικοί τύποι έξυπνων δεικτών στη βιβλιοθήκη C++:

  • std::unique_ptr
  • std::shared_ptr
  • std::weak_ptr

std::unique_ptr

  • Κατέχει πόρο αποκλειστικά.
  • Δεν μπορεί να αντιγραφεί, αλλά μπορεί να μετακινηθεί.
  • Χρησιμοποιείται για μοναδική κατοχή πόρου.
  • Οι επιπλέον δαπάνες είναι ελάχιστες, ισοδύναμες με έναν ωμό δείκτη.
// παράδειγμα unique_ptr
#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << *ptr << std::endl; // 10
    // std::unique_ptr<int> ptr2 = ptr; // Σφάλμα μεταγλώττισης: το unique_ptr δεν αντιγράφεται
    std::unique_ptr<int> ptr3 = std::move(ptr); // Μεταφορά κατοχής
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Μη ορισμένη συμπεριφορά: το ptr τώρα είναι κενό
    return 0;
}

std::shared_ptr

  • Επιτρέπει σε πολλούς δείκτες να κατέχουν κοινό πόρο.
  • Χρησιμοποιεί μετρητή αναφορών. Η μνήμη απελευθερώνεται όταν ο μετρητής γίνει μηδέν.
  • Μπορεί να αντιγραφεί. Κάθε αντίγραφο αυξάνει τον μετρητή αναφορών.
  • Έχει υψηλότερα έξοδα σε σύγκριση με το unique_ptr λόγω διαχείρισης του μετρητή αναφορών.
// shared_ptr παράδειγμα
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 1)
    std::shared_ptr<int> ptr2 = ptr1; // Αντιγραφή, αυξάνει το use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Άλλη μια αντιγραφή
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Δεν κατέχει πόρο και δεν αυξάνει τον μετρητή αναφορών.
  • Χρησιμοποιείται για την επίλυση του προβλήματος κυκλικών αναφορών μεταξύ shared_ptr.
  • Επιτρέπει την πρόσβαση στον πόρο που δείχνει το shared_ptr, αλλά δεν εμποδίζει την διαγραφή του.
  • Για πρόσβαση στον πόρο, πρέπει να μετατρέψετε το weak_ptr σε shared_ptr με τη μέθοδο lock().
// weak_ptr παράδειγμα
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> shared_ptr_int = std::make_shared<int>(30);
    std::weak_ptr<int> weak_ptr_int = shared_ptr_int;

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl; // 30
    } else {
        std::cout << "Ο πόρος έχει διαγραφεί." << std::endl;
    }

    shared_ptr_int.reset(); // Ο πόρος απελευθερώνεται

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Ο πόρος έχει διαγραφεί." << std::endl; // Ο πόρος έχει διαγραφεί.
    }
    return 0;
}

Η χρήση έξυπνων δεικτών αποτελεί καλή πρακτική στη σύγχρονη C++, καθώς μειώνει σημαντικά την πιθανότητα σφαλμάτων διαχείρισης μνήμης.