C++ Δείκτες με παραδείγματα
Τι είναι οι δείκτες;
In C++, ένας δείκτης αναφέρεται σε μια μεταβλητή που διατηρεί τη διεύθυνση μιας άλλης μεταβλητής. Όπως οι κανονικές μεταβλητές, οι δείκτες έχουν τύπο δεδομένων. Για παράδειγμα, ένας δείκτης τύπου integer μπορεί να κρατήσει τη διεύθυνση μιας μεταβλητής τύπου integer. Ένας δείκτης τύπου χαρακτήρα μπορεί να κρατήσει τη διεύθυνση μιας μεταβλητής τύπου χαρακτήρων.
Θα πρέπει να δείτε έναν δείκτη ως συμβολική αναπαράσταση μιας διεύθυνσης μνήμης. Με δείκτες, τα προγράμματα μπορούν να προσομοιώσουν κλήση προς αναφορά. Μπορούν επίσης να δημιουργήσουν και να χειριστούν δυναμικές δομές δεδομένων. Σε C++, μια μεταβλητή δείκτη αναφέρεται σε μια μεταβλητή που δείχνει σε μια συγκεκριμένη διεύθυνση σε μια μνήμη που επισημαίνεται από μια άλλη μεταβλητή.
Διευθύνσεις σε C++
Να καταλαβεις C++ δείκτες, πρέπει να κατανοήσετε πώς οι υπολογιστές αποθηκεύουν δεδομένα.
Όταν δημιουργείτε μια μεταβλητή στο δικό σας C++ του προγράμματος, του εκχωρείται χώρος στη μνήμη του υπολογιστή. Η τιμή αυτής της μεταβλητής αποθηκεύεται στην εκχωρημένη θέση.
Για να γνωρίζετε τη θέση στη μνήμη του υπολογιστή όπου είναι αποθηκευμένα τα δεδομένα, C++ παρέχει το & (αναφορά) χειριστή. Ο χειριστής επιστρέφει τη διεύθυνση που καταλαμβάνει μια μεταβλητή.
Για παράδειγμα, εάν το x είναι μια μεταβλητή, το &x επιστρέφει τη διεύθυνση της μεταβλητής.
Σύνταξη δήλωσης δείκτη
Η δήλωση του C++ παίρνει την ακόλουθη σύνταξη:
datatype *variable_name;
- Ο τύπος δεδομένων είναι ο βασικός τύπος του δείκτη που πρέπει να είναι έγκυρος C++ τύπου δεδομένων.
- Το variable_name is θα πρέπει να είναι το όνομα της μεταβλητής δείκτη.
- Ο αστερίσκος που χρησιμοποιείται παραπάνω για τη δήλωση δείκτη είναι παρόμοιος με τον αστερίσκο που χρησιμοποιείται για την εκτέλεση της λειτουργίας πολλαπλασιασμού. Είναι ο αστερίσκος που επισημαίνει τη μεταβλητή ως δείκτη.
Ακολουθεί ένα παράδειγμα έγκυρων δηλώσεων δείκτη στο C++:
int *x; // a pointer to integer double *x; // a pointer to double float *x; // a pointer to float char *ch // a pointer to a character
Τελεστής αναφοράς (&) και τελεστής αναφοράς (*)
Ο τελεστής αναφοράς (&) επιστρέφει τη διεύθυνση της μεταβλητής.
Ο τελεστής αποαναφοράς (*) μας βοηθά να λάβουμε την τιμή που έχει αποθηκευτεί σε μια διεύθυνση μνήμης.
Για παράδειγμα:
Εάν έχουμε μια μεταβλητή με το όνομα num, αποθηκευμένη στη διεύθυνση 0x234 και αποθήκευση της τιμής 28.
Ο τελεστής αναφοράς (&) θα επιστρέψει 0x234.
Ο τελεστής αποσύνδεσης (*) θα επιστρέψει 5.
Παράδειγμα 1:
#include <iostream> using namespace std; int main() { int x = 27; int *ip; ip = &x; cout << "Value of x is : "; cout << x << endl; cout << "Value of ip is : "; cout << ip<< endl; cout << "Value of *ip is : "; cout << *ip << endl; return 0; }
Παραγωγή:
Πώς λειτουργεί αυτό:
Εδώ είναι ένα στιγμιότυπο οθόνης του κώδικα:
Επεξήγηση κώδικα:
- Εισαγάγετε το αρχείο κεφαλίδας iostream. Αυτό θα μας επιτρέψει να χρησιμοποιήσουμε τις λειτουργίες που ορίζονται στο αρχείο κεφαλίδας χωρίς να λαμβάνουμε σφάλματα.
- Συμπεριλάβετε τον χώρο ονομάτων std για να χρησιμοποιήσετε τις κλάσεις του χωρίς να τον καλέσετε.
- Καλέστε τη συνάρτηση main(). Η λογική του προγράμματος πρέπει να προστεθεί στο σώμα αυτής της συνάρτησης. Το { σηματοδοτεί την αρχή του σώματος της συνάρτησης.
- Δηλώστε μια ακέραια μεταβλητή x και ορίστε της μια τιμή 27.
- Δηλώστε μια μεταβλητή δείκτη *ip.
- Αποθηκεύστε τη διεύθυνση της μεταβλητής x στη μεταβλητή δείκτη.
- Εκτυπώστε λίγο κείμενο στην κονσόλα.
- Εκτυπώστε την τιμή της μεταβλητής x στην οθόνη.
- Εκτυπώστε λίγο κείμενο στην κονσόλα.
- Εκτυπώστε τη διεύθυνση της μεταβλητής x. Η τιμή της διεύθυνσης αποθηκεύτηκε στη μεταβλητή ip.
- Εκτυπώστε λίγο κείμενο στην κονσόλα.
- Η τιμή εκτύπωσης είναι αποθηκευμένη στη διεύθυνση του δείκτη.
- Το πρόγραμμα θα πρέπει να επιστρέψει τιμή μετά την επιτυχή εκτέλεση.
- Τέλος του σώματος της συνάρτησης main().
Δείκτες και Πίνακες
Οι πίνακες και οι δείκτες λειτουργούν με βάση μια σχετική έννοια. Υπάρχουν διάφορα πράγματα που πρέπει να προσέξετε όταν εργάζεστε με πίνακες που έχουν δείκτες. Το ίδιο το όνομα του πίνακα υποδηλώνει τη διεύθυνση βάσης του πίνακα. Αυτό σημαίνει ότι για να αντιστοιχίσετε τη διεύθυνση ενός πίνακα σε έναν δείκτη, δεν πρέπει να χρησιμοποιήσετε συμπλεκτικό σύμφωνο (&).
Για παράδειγμα:
p = arr;
Τα παραπάνω είναι σωστά αφού το arr αντιπροσωπεύει τη διεύθυνση των πινάκων. Εδώ είναι ένα άλλο παράδειγμα:
p = &arr;
Τα παραπάνω είναι λανθασμένα.
Μπορούμε σιωπηρά να μετατρέψουμε έναν πίνακα σε δείκτη. Για παράδειγμα:
int arr [20]; int * ip;
Παρακάτω είναι μια έγκυρη λειτουργία:
ip = arr;
Μετά την παραπάνω δήλωση, το ip και το arr θα είναι ισοδύναμα και θα μοιράζονται ιδιότητες. Ωστόσο, μπορεί να εκχωρηθεί διαφορετική διεύθυνση στο ip, αλλά δεν μπορούμε να εκχωρήσουμε τίποτα στο arr.
Παράδειγμα 2:
Αυτό το παράδειγμα δείχνει πώς να διασχίσετε έναν πίνακα χρησιμοποιώντας δείκτες:
#include <iostream> using namespace std; int main() { int *ip; int arr[] = { 10, 34, 13, 76, 5, 46 }; ip = arr; for (int x = 0; x < 6; x++) { cout << *ip << endl; ip++; } return 0; }
Παραγωγή:
Εδώ είναι ένα στιγμιότυπο οθόνης του κώδικα:
Επεξήγηση κώδικα:
- Δηλώστε μια ακέραια μεταβλητή δείκτη ip.
- Δηλώστε έναν πίνακα με το όνομα arr και αποθηκεύστε 6 ακέραιους αριθμούς σε αυτόν.
- Αντιστοιχίστε το arr στο ip. Το ip και το arr θα γίνουν ισοδύναμα.
- Δημιουργήστε έναν βρόχο for. Η μεταβλητή βρόχου x δημιουργήθηκε για να επαναλαμβάνεται πάνω από τα στοιχεία του πίνακα από το δείκτη 0 έως το 5.
- Εκτυπώστε τις τιμές που είναι αποθηκευμένες στη διεύθυνση της IP του δείκτη. Θα επιστραφεί μία τιμή ανά επανάληψη και θα γίνουν συνολικά 6 επαναλήψεις. Το endl είναι α C++ λέξη-κλειδί που σημαίνει την τελική γραμμή. Αυτή η ενέργεια σάς επιτρέπει να μετακινήσετε τον κέρσορα στην επόμενη γραμμή μετά την εκτύπωση κάθε τιμής. Κάθε τιμή θα εκτυπωθεί σε μεμονωμένη γραμμή.
- Για να μετακινήσετε το δείκτη στην επόμενη θέση int μετά από κάθε επανάληψη.
- Τέλος του for a loop.
- Το πρόγραμμα πρέπει να επιστρέψει κάτι μετά την επιτυχή εκτέλεση.
- Τέλος του σώματος της συνάρτησης main().
NULL δείκτης
Εάν δεν υπάρχει ακριβής διεύθυνση που πρόκειται να εκχωρηθεί, τότε στη μεταβλητή δείκτη μπορεί να εκχωρηθεί NULL. Θα πρέπει να γίνει κατά τη διάρκεια της δήλωσης. Ένας τέτοιος δείκτης είναι γνωστός ως μηδενικός δείκτης. Η τιμή του είναι μηδέν και ορίζεται σε πολλές τυπικές βιβλιοθήκες όπως το iostream.
Παράδειγμα 3:
#include <iostream> using namespace std; int main() { int *ip = NULL; cout << "Value of ip is: " << ip; return 0; }
Παραγωγή:
Εδώ είναι ένα στιγμιότυπο οθόνης του κώδικα:
Επεξήγηση κώδικα:
- Δηλώστε μια μεταβλητή δείκτη ip και εκχωρήστε της μια τιμή NULL.
- Εκτυπώστε την τιμή της μεταβλητής δείκτη ip μαζί με κάποιο κείμενο στην κονσόλα.
- Το πρόγραμμα πρέπει να επιστρέψει τιμή μετά την επιτυχή ολοκλήρωση.
- Τέλος του σώματος της συνάρτησης main().
Δείκτες μεταβλητών
Με C++, μπορείτε να χειριστείτε δεδομένα απευθείας από τη μνήμη του υπολογιστή.
Ο χώρος μνήμης μπορεί να εκχωρηθεί ή να εκχωρηθεί ξανά όπως επιθυμεί κανείς. Αυτό γίνεται εφικτό από τις μεταβλητές Pointer.
Οι μεταβλητές δείκτη παραπέμπουν σε μια συγκεκριμένη διεύθυνση στη μνήμη του υπολογιστή που δείχνει μια άλλη μεταβλητή.
Μπορεί να δηλωθεί ως εξής:
int *p;
Ή,
int* p;
Στο παράδειγμα σας, έχουμε δηλώσει τη μεταβλητή δείκτη p.
Θα έχει μια διεύθυνση μνήμης.
Ο αστερίσκος είναι ο τελεστής παραπομπής που σημαίνει δείκτη προς.
Ο δείκτης p δείχνει μια ακέραια τιμή στη διεύθυνση μνήμης.
Παράδειγμα 4:
#include <iostream> using namespace std; int main() { int *p, x = 30; p = &x; cout << "Value of x is: " << *p; return 0; }
Παραγωγή:
Εδώ είναι ένα στιγμιότυπο οθόνης του κώδικα:
Επεξήγηση κώδικα:
- Δηλώστε μια μεταβλητή δείκτη p και μια μεταβλητή x με τιμή 30.
- Αντιστοιχίστε τη διεύθυνση της μεταβλητής x στο p.
- Εκτυπώστε την τιμή της μεταβλητής δείκτη p μαζί με κάποιο κείμενο στην κονσόλα.
- Το πρόγραμμα πρέπει να επιστρέψει τιμή μετά την επιτυχή ολοκλήρωση.
- Τέλος του σώματος της συνάρτησης main().
Εφαρμογή Δεικτών
Λειτουργίες σε C++ μπορεί να επιστρέψει μόνο μία τιμή. Επιπλέον, όλες οι μεταβλητές που δηλώνονται σε μια συνάρτηση κατανέμονται στη στοίβα κλήσης συναρτήσεων. Μόλις επιστρέψει η συνάρτηση, όλες οι μεταβλητές στοίβας καταστρέφονται.
Τα ορίσματα για τη συνάρτηση μεταβιβάζονται με τιμή και οποιαδήποτε τροποποίηση γίνεται στις μεταβλητές δεν αλλάζει την τιμή των πραγματικών μεταβλητών που μεταβιβάζονται. Το ακόλουθο παράδειγμα βοηθά στην κατανόηση αυτής της έννοιας:
Παράδειγμα 5:
#include <iostream> using namespace std; void test(int*, int*); int main() { int a = 5, b = 5; cout << "Before changing:" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; test(&a, &b); cout << "\nAfter changing" << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; return 0; } void test(int* n1, int* n2) { *n1 = 10; *n2 = 11; }
Παραγωγή:
Εδώ είναι ένα στιγμιότυπο οθόνης του κώδικα:
Επεξήγηση κώδικα:
- Δημιουργήστε ένα πρωτότυπο μιας συνάρτησης με το όνομα test που θα λάβει δύο ακέραιους αριθμούς.
- Καλέστε τη συνάρτηση main(). Θα προσθέσουμε τη λογική του προγράμματος μέσα στο σώμα του.
- Δηλώστε δύο ακέραιες μεταβλητές a και b, η καθεμία με τιμή 5.
- Εκτυπώστε λίγο κείμενο στην κονσόλα. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή.
- Εκτυπώστε την τιμή της μεταβλητής a στην κονσόλα μαζί με άλλο κείμενο. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή.
- Εκτυπώστε την τιμή της μεταβλητής b στην κονσόλα μαζί με άλλο κείμενο. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή.
- Δημιουργήστε μια συνάρτηση με το όνομα test() που λαμβάνει τις διευθύνσεις της μεταβλητής a και b ως παραμέτρους.
- Εκτυπώστε λίγο κείμενο στην κονσόλα. Το \n θα δημιουργήσει μια νέα κενή γραμμή πριν από την εκτύπωση του κειμένου. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή μετά την εκτύπωση του κειμένου.
- Εκτυπώστε την τιμή της μεταβλητής a στην κονσόλα μαζί με άλλο κείμενο. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή.
- Εκτυπώστε την τιμή της μεταβλητής b στην κονσόλα μαζί με άλλο κείμενο. Το endl (τελική γραμμή) θα μετακινήσει τον κέρσορα για να ξεκινήσει η εκτύπωση στην επόμενη γραμμή.
- Το πρόγραμμα πρέπει να επιστρέψει τιμή μετά την επιτυχή ολοκλήρωση.
- Τέλος του σώματος της συνάρτησης main().
- Καθορισμός της δοκιμής συνάρτησης (). Η συνάρτηση θα πρέπει να λάβει δύο ακέραιες μεταβλητές δείκτη *n1 και *n2.
- Εκχωρώντας στη μεταβλητή δείκτη *n1 μια τιμή 10.
- Εκχωρώντας στη μεταβλητή δείκτη *n2 μια τιμή 11.
- Τέλος του σώματος της δοκιμής συνάρτησης().
Ακόμα κι αν, οι νέες τιμές εκχωρούνται στη μεταβλητή a και b μέσα στη δοκιμή συνάρτησης, μόλις ολοκληρωθεί η κλήση συνάρτησης, δεν αντικατοπτρίζεται το ίδιο στην κύρια εξωτερική συνάρτηση.
Η χρήση δεικτών ως ορισμάτων συνάρτησης βοηθά στη μεταβίβαση της πραγματικής διεύθυνσης της μεταβλητής στη συνάρτηση και όλες οι αλλαγές που πραγματοποιούνται στη μεταβλητή θα αντικατοπτρίζονται στην εξωτερική συνάρτηση.
Στην παραπάνω περίπτωση, η συνάρτηση «test» έχει τη διεύθυνση των μεταβλητών «a» και «b». Αυτές οι δύο μεταβλητές είναι άμεσα προσβάσιμες από τη συνάρτηση «δοκιμή» και επομένως οποιαδήποτε αλλαγή γίνεται σε αυτές τις μεταβλητές αντικατοπτρίζεται στη συνάρτηση καλούντος «κύρια».
Πλεονεκτήματα της χρήσης Pointers
Εδώ, είναι τα πλεονεκτήματα/πλεονεκτήματα από τη χρήση των δεικτών
- Οι δείκτες είναι μεταβλητές που αποθηκεύουν τη διεύθυνση άλλων μεταβλητές σε C++.
- Περισσότερες από μία μεταβλητές μπορούν να τροποποιηθούν και να επιστραφούν με συνάρτηση χρησιμοποιώντας δείκτες.
- Η μνήμη μπορεί να εκχωρηθεί δυναμικά και να αποδεσμευτεί χρησιμοποιώντας δείκτες.
- Οι δείκτες βοηθούν στην απλοποίηση της πολυπλοκότητας του προγράμματος.
- Η ταχύτητα εκτέλεσης ενός προγράμματος βελτιώνεται χρησιμοποιώντας δείκτες.
Περίληψη
- Ένας δείκτης αναφέρεται σε μια μεταβλητή που διατηρεί τη διεύθυνση μιας άλλης μεταβλητής.
- Κάθε δείκτης έχει έναν έγκυρο τύπο δεδομένων.
- Ένας δείκτης είναι μια συμβολική αναπαράσταση μιας διεύθυνσης μνήμης.
- Οι δείκτες επιτρέπουν στα προγράμματα να προσομοιώνουν κλήση προς αναφορά και να δημιουργούν και να χειρίζονται δυναμικές δομές δεδομένων.
- Array και οι δείκτες χρησιμοποιούν μια σχετική έννοια.
- Το όνομα του πίνακα υποδηλώνει τη βάση του πίνακα.
- Εάν θέλετε να αντιστοιχίσετε τη διεύθυνση ενός πίνακα σε έναν δείκτη, μην χρησιμοποιείτε συμπλεκτικό σύμφωνο (&).
- Εάν δεν υπάρχει συγκεκριμένη διεύθυνση για να εκχωρήσετε μια μεταβλητή δείκτη, εκχωρήστε της ένα NULL.