Σπίτι Προσωπικά Οικονομικά Πώς το Heap λειτουργεί σε C ++ - dummies

Πώς το Heap λειτουργεί σε C ++ - dummies

Πίνακας περιεχομένων:

Βίντεο: Αλγόριθμος ταξινόμησης Heapsort 2024

Βίντεο: Αλγόριθμος ταξινόμησης Heapsort 2024
Anonim

Ο σωρός είναι ένα άμορφο μπλοκ μνήμης που το πρόγραμμά σας C ++ μπορεί να έχει πρόσβαση όπως είναι απαραίτητο. Μάθετε γιατί υπάρχει και πώς να το χρησιμοποιήσετε.

Ακριβώς όπως είναι δυνατόν να περάσετε έναν δείκτη σε μια λειτουργία, είναι πιθανό μια λειτουργία να επιστρέψει έναν δείκτη. Μια συνάρτηση που επιστρέφει τη διεύθυνση ενός διπλού δηλώνεται ως εξής:

double * fn (void);

Ωστόσο, πρέπει να είστε πολύ προσεκτικοί κατά την επιστροφή ενός δείκτη. Για να κατανοήσετε τους κινδύνους, πρέπει να γνωρίζετε κάτι σχετικά με την μεταβλητή εμβέλεια.

Περιορισμένη εμβέλεια σε C ++

Πεδίο εφαρμογής είναι η περιοχή στην οποία ορίζεται μια μεταβλητή. Εξετάστε το ακόλουθο απόσπασμα κώδικα:

// η ακόλουθη μεταβλητή είναι προσβάσιμη σε // όλες τις λειτουργίες και ορίζεται όσο το πρόγραμμα // εκτελείται (global scope) int intGlobal; // η ακόλουθη μεταβλητή intChild είναι προσβάσιμη // μόνο στη συνάρτηση και ορίζεται μόνο // εφόσον η C ++ εκτελεί child () ή a // που καλεί child () (πεδίο λειτουργίας) void child (void) {int intChild;} // η ακόλουθη μεταβλητή intParent έχει τη λειτουργία // scope void parent (void) {int intParent = 0; παιδί(); int intLater = 0; (int nArgs, char * pArgs []) {parent ();}

Αυτό το κομμάτι του προγράμματος ξεκινά με τη δήλωση μιας μεταβλητής intGlobal. Αυτή η μεταβλητή υπάρχει από τη στιγμή που ξεκινάει η εκτέλεση του προγράμματος μέχρι να τερματιστεί. Λέτε ότι το intGlobal έχει πεδίο εφαρμογής. "Μπορείτε επίσης να πείτε ότι η μεταβλητή" πηγαίνει στο πεδίο "ακόμα και πριν την κλήση της κύριας λειτουργίας ().

Η κύρια λειτουργία () επικαλείται αμέσως γονέα (). Το πρώτο πράγμα που ο επεξεργαστής βλέπει στον γονέα () είναι η δήλωση του intParent. Σε αυτό το σημείο, το intParent μπαίνει στο πεδίο - δηλαδή, το intParent ορίζεται και διατίθεται για το υπόλοιπο της γονικής συνάρτησης ().

Η δεύτερη πρόταση στο γονικό () είναι η κλήση προς το παιδί (). Για άλλη μια φορά, η λειτουργία child () δηλώνει μια τοπική μεταβλητή, αυτή τη φορά intChild. Το εύρος της μεταβλητής intChild περιορίζεται στη λειτουργία child (). Από τεχνική άποψη, το intparent δεν ορίζεται στο πεδίο του child () επειδή το child () δεν έχει πρόσβαση στο intParent. Ωστόσο, η μεταβλητή intParent εξακολουθεί να υπάρχει ενώ εκτελείται το child ().

Όταν το παιδί () εξέρχεται, η μεταβλητή intChild εξέρχεται από το πεδίο εφαρμογής. Όχι μόνο το intChild δεν είναι πλέον προσβάσιμο, δεν υπάρχει πια. (Η μνήμη που καταλαμβάνεται από το intChild επιστρέφει στη γενική ομάδα για να χρησιμοποιηθεί για άλλα πράγματα.)

Καθώς ο γονέας () συνεχίζει να εκτελεί, η μεταβλητή intLater μπαίνει στο πεδίο εφαρμογής στη δήλωση. Στο σημείο που ο γονέας () επιστρέφει στο main (), τόσο το intParent όσο και το intLater εξέρχονται από το πεδίο εφαρμογής.

Επειδή το intGlobal δηλώνεται παγκοσμίως σε αυτό το παράδειγμα, είναι διαθέσιμο και στις τρεις λειτουργίες και παραμένει διαθέσιμο για τη διάρκεια ζωής του προγράμματος.

Εξετάζοντας το πρόβλημα της εμβέλειας στο C ++

Το επόμενο τμήμα κώδικα μεταγλωττίζεται χωρίς σφάλμα αλλά δεν λειτουργεί (δεν το μισείτε ακριβώς;):

double * child (void) {double dLocalVariable; επιστροφή & dLocalVariable;} άκυρη μητρική (άκυρη) {διπλή * pdLocal; pdLocal = παιδί (); * pdLocal = 1. 0;}

Το πρόβλημα με αυτή τη λειτουργία είναι ότι το dLocalVariable ορίζεται μόνο μέσα στο πεδίο της λειτουργίας child (). Έτσι, από τη στιγμή που η διεύθυνση μνήμης της dLocalVariable επιστρέφεται από child (), αναφέρεται σε μια μεταβλητή που δεν υπάρχει πια. Η μνήμη που κατά το παρελθόν κατείχε η dLocalVariable χρησιμοποιείται μάλλον για κάτι άλλο.

Αυτό το σφάλμα είναι πολύ συνηθισμένο επειδή μπορεί να ερπετεύσει με διάφορους τρόπους. Δυστυχώς, αυτό το σφάλμα δεν αναγκάζει το πρόγραμμα να σταματήσει αμέσως. Στην πραγματικότητα, το πρόγραμμα μπορεί να λειτουργήσει καλά τις περισσότερες φορές - δηλαδή, το πρόγραμμα συνεχίζει να λειτουργεί όσο η μνήμη που παλαιότερα κατέλαβε η dLocalVariable δεν επαναχρησιμοποιείται αμέσως. Τέτοια διαλείπουσα προβλήματα είναι τα πιο δύσκολα για την επίλυση.

Παρέχει μια λύση χρησιμοποιώντας το σωρό στο C ++

Το πρόβλημα εύρους προέκυψε επειδή η C ++ πήρε πίσω την τοπικά καθορισμένη μνήμη πριν από την προετοιμασία του προγραμματιστή. Αυτό που χρειάζεται είναι ένα μπλοκ μνήμης που ελέγχεται από τον προγραμματιστή. Μπορεί να διαθέσει τη μνήμη και να την επαναφέρει όταν θέλει - όχι επειδή η C ++ σκέφτεται ότι είναι καλή ιδέα. Ένα τέτοιο μπλοκ μνήμης ονομάζεται σωρός.

Η μνήμη σωρού διατίθεται χρησιμοποιώντας τη νέα λέξη-κλειδί ακολουθούμενη από τον τύπο αντικειμένου που θα διαθέσετε. Η νέα εντολή σπάει ένα κομμάτι μνήμης από το σωρό αρκετά μεγάλο για να κρατήσει τον καθορισμένο τύπο αντικειμένου και να επιστρέψει τη διεύθυνσή του. Για παράδειγμα, το ακόλουθο διαθέτει μια διπλή μεταβλητή από τον σωρό:

διπλό * παιδί (κενό) {διπλό * pdLocalVariable = νέο διπλό; επιστροφή pdLocalVariable;}

Αυτή η λειτουργία λειτουργεί τώρα σωστά. Παρόλο που η μεταβλητή pdLocalVariable σβήνει από το πεδίο εφαρμογής όταν η λειτουργία child () επιστρέφει, η μνήμη στην οποία αναφέρεται το pdLocalVariable δεν ισχύει. Μια θέση μνήμης που επιστρέφεται με νέα δεν εξέρχεται από το πεδίο εφαρμογής μέχρι να επιστραφεί ρητά στον σωρό χρησιμοποιώντας τη διαγραφή λέξης κλειδιού, η οποία έχει σχεδιαστεί ειδικά για το σκοπό αυτό:

void parent (void) {// child () επιστρέφει τη διεύθυνση ενός μπλοκ // μνήμης σωρού διπλό * pdMyDouble = παιδί (); // αποθηκεύστε μια τιμή εκεί * pdMyDouble = 1. 1; // … // τώρα επιστρέφει τη μνήμη στο σωρό διαγραφή pdMyDouble; pdMyDouble = 0; // …}

Εδώ ο δείκτης που επιστρέφεται από το παιδί () χρησιμοποιείται για να αποθηκεύσει μια διπλή τιμή. Μετά την ολοκλήρωση της λειτουργίας με τη θέση της μνήμης, αυτή επιστρέφεται στον σωρό. Η γονική συνάρτηση () θέτει το δείκτη στο 0 μετά την επιστροφή της μνήμης σωρού - αυτό δεν είναι μια απαίτηση, αλλά είναι μια πολύ καλή ιδέα.

Αν ο προγραμματιστής προσπαθήσει λανθασμένα να αποθηκεύσει κάτι στο * pdMyDouble μετά τη διαγραφή, το πρόγραμμα θα σβήσει αμέσως με ένα σημαντικό μήνυμα σφάλματος.

Μπορείτε να χρησιμοποιήσετε καινούργια για να αντιστοιχίσετε συστοιχίες από τον σωρό, αλλά πρέπει να επιστρέψετε έναν πίνακα χρησιμοποιώντας τη λέξη κλειδί διαγραφής [999] int * nArray = new int [10]. nArray [0] = 0. διαγραφή [] nArray;

Τεχνικά νέο int [10] επικαλείται τον νέο χειριστή [], αλλά λειτουργεί το ίδιο με νέο.
Πώς το Heap λειτουργεί σε C ++ - dummies

Η επιλογή των συντακτών

Πώς να αλλάξετε τη ρύθμιση ισορροπίας λευκού σε ετικέτες Canon EOS 70D

Πώς να αλλάξετε τη ρύθμιση ισορροπίας λευκού σε ετικέτες Canon EOS 70D

Χρησιμοποιώντας το Ο έλεγχος εξισορρόπησης λευκού στο Canon EOS 70D σας μπορεί εύκολα και γρήγορα να διορθώσει προβλήματα χρώματος. Οι διαθέσιμες ρυθμίσεις ισορροπίας λευκού απεικονίζονται με τα σύμβολα που εμφανίζονται στον παρακάτω πίνακα. Μπορείτε να δείτε την τρέχουσα ρύθμιση στην οθόνη Ρυθμίσεις λήψης, όπως φαίνεται στο παρακάτω σχήμα. Για να προσαρμόσετε τη ρύθμιση, έχετε ...

Η επιλογή των συντακτών

Προετοιμασία αντιγράφου TIFF ψηφιακής εικόνας για δημοσίευση - ανδρεικέλες

Προετοιμασία αντιγράφου TIFF ψηφιακής εικόνας για δημοσίευση - ανδρεικέλες

Μπορείτε να δημιουργήσετε αντίγραφο TIFF ψηφιακής εικόνας εύκολα. Για παράδειγμα, εάν θέλετε να υποβάλετε μια ψηφιακή φωτογραφία σε μια δημοσίευση εκτύπωσης, χρειάζεστε ένα αρχείο φωτογραφίας μορφής TIFF. Για να δημιουργήσετε ένα αντίγραφο TIFF ενός αρχείου σε ένα πρόγραμμα επεξεργασίας φωτογραφιών:

Εξάγοντας το περίγραμμα επιλογής του ψηφιακού σας επεξεργαστή εικόνας - ανδρείκελα

Εξάγοντας το περίγραμμα επιλογής του ψηφιακού σας επεξεργαστή εικόνας - ανδρείκελα

Η πρώτη προσπάθεια. Αναμείνετε να βελτιώσετε το περίγραμμα επιλογής σας τουλάχιστον λίγο. Μπορείτε να βελτιώσετε το περίγραμμα σας με διάφορους τρόπους: Αντίστροφη περιγράμματος επιλογής: Απλά χρησιμοποιήστε την εντολή Invert (ή την αντίστοιχη εντολή του προγράμματος). Προσθέστε σε περίγραμμα επιλογής: ...

Επιλογή από τις άκρες της ψηφιακής εικόνας - ανδρείκελα

Επιλογή από τις άκρες της ψηφιακής εικόνας - ανδρείκελα

Όπου οι φωτεινές περιοχές πληρούν τις σκοτεινές περιοχές. Πολλά προγράμματα επεξεργασίας φωτογραφιών σας επιτρέπουν να σχεδιάσετε ένα περίγραμμα επιλογής κατά μήκος ενός άκρου. Το εργαλείο αναζητά άκρες κοντά στο σημείο που σύρετε το ποντίκι.

Η επιλογή των συντακτών

Πώς να χρησιμοποιείτε το παράθυρο μητρώου του QuickBooks 2010 - dummies

Πώς να χρησιμοποιείτε το παράθυρο μητρώου του QuickBooks 2010 - dummies

Για να εργαστείτε ευκολότερα με το παράθυρο του Μητρώου και να ελέγξετε τον τρόπο εμφάνισής του: Το κουμπί Μετάβαση: Εμφανίζει το παράθυρο διαλόγου Μετάβαση (Go To). Αυτό το παράθυρο διαλόγου σάς επιτρέπει να αναζητήσετε μια συναλλαγή στο παράθυρο "Εγγραφή". Για παράδειγμα, μπορείτε να αναζητήσετε ...

Πώς να εργάζεστε με έναν υπάρχοντα προϋπολογισμό σε QuickBooks - dummies

Πώς να εργάζεστε με έναν υπάρχοντα προϋπολογισμό σε QuickBooks - dummies

Σε μεγάλες εταιρείες με εκατοντάδες ή χιλιάδες εργαζόμενοι, δύο ή τρία άτομα δαπανούν μεγάλο μέρος ή και ολόκληρο το χρόνο εργασίας τους με τα στοιχεία που έχουν εγγραφεί στον προϋπολογισμό. Για να επεξεργαστείτε έναν υπάρχοντα προϋπολογισμό στο QuickBooks, ακολουθήστε τα παρακάτω βήματα:

Πώς να χρησιμοποιείτε τα κουτιά παραθύρων αναφορών του QuickBooks - dummies

Πώς να χρησιμοποιείτε τα κουτιά παραθύρων αναφορών του QuickBooks - dummies

Από, Προς, Στήλες και Ταξινόμηση. Αυτά τα πλαίσια σας επιτρέπουν επίσης να ελέγχετε τις πληροφορίες που εμφανίζονται στο παράθυρο αναφοράς και την εμφάνιση των πληροφοριών. Για παράδειγμα, μπορείτε να ενημερώσετε το QuickBooks για το χρονικό διάστημα που θέλετε ...