| Both sides previous revision
Previous revision
Next revision
|
Previous revision
Next revision
Both sides next revision
|
cpp:object_lifecycle [2020/04/14 14:00] gthanos |
cpp:object_lifecycle [2021/05/07 07:33] gthanos [Ένα πιο σύνθετο παράδειγμα αρχικοποίησης δεικτών] |
| |
| ====== Κύκλος ζωής των αντικειμένων - Δημιουργία και ανάθεση αντικειμένων στο heap ====== | ====== Κύκλος ζωής των αντικειμένων - Δημιουργία αντικειμένων μέσω δυναμικής δέσμευσης μνήμης ====== |
| |
| Παρακάτω δίνεται ο κώδικας της κλάσης //Rectangle// τον οποίο θα χρησιμοποιήσουμε για να μεταγλωττίσουμε και να εκτελέσουμε τα παραδείγματα που ακολουθούν. Η παρούσα κλάση αποτελείται από δύο πεδία τύπου int* (για την αποθήκευση του width και του height αντιστοίχως). Κατά την κατασκευή ενός αντικειμένου θα πρέπει απαραίτητα να δεσμεύεται ο απαιτούμενος χώρος για την αποθήκευση των τιμών του πλάτους και του ύψους. Κατά την καταστροφή του αντικειμένου ο χώρος που δεσμεύτηκε θα πρέπει να αποδεσμευθεί στον καταστροφέα. | Παρακάτω δίνεται ο κώδικας της κλάσης //Rectangle// τον οποίο θα χρησιμοποιήσουμε για να μεταγλωττίσουμε και να εκτελέσουμε τα παραδείγματα που ακολουθούν. Η παρούσα κλάση αποτελείται από δύο πεδία τύπου int* (για την αποθήκευση του width και του height αντιστοίχως). Κατά την κατασκευή ενός αντικειμένου θα πρέπει απαραίτητα να δεσμεύεται ο απαιτούμενος χώρος για την αποθήκευση των τιμών του πλάτους και του ύψους. Κατά την καταστροφή του αντικειμένου ο χώρος που δεσμεύτηκε θα πρέπει να αποδεσμευτεί στον καταστροφέα. |
| |
| <code cpp Rectangle.hpp> | <code cpp Rectangle.hpp> |
| } | } |
| </code> | </code> |
| |
| Όταν δεν χρειαζόμαστε πλέον το αντικείμενο που δεσμεύτηκε δυναμικά στο //heap// θα πρέπει να το καταστρέψουμε ελευθερώνοντας τη δεσμευμένη μνήμη με τη βοήθεια του τελεστή //delete//. Κατά την απελευθέρωση της μνήμης μέσω του τελεστή //delete// καλείται ο καταστροφέας της κλάσης, σε αναλογία με την κλήση του κατασκευαστή της κλάσης με χρήση του τελεστή //new//. | |
| |
| Ακολουθεί το σχηματικό διάγραμμα του //stack// και του //heap// της διεργασίας πριν, κατά τη διάρκεια και μετά την εκτέλεσης της συνάρτησης //foo//. Στο διάγραμμα δεν αποτυπώνεται η δέσμευση μνήμης για τα πεδία //width// και //height// του κάθε αντικειμένου τύπου //Rectangle//. | Ακολουθεί το σχηματικό διάγραμμα του //stack// και του //heap// της διεργασίας πριν, κατά τη διάρκεια και μετά την εκτέλεσης της συνάρτησης //foo//. Στο διάγραμμα δεν αποτυπώνεται η δέσμευση μνήμης για τα πεδία //width// και //height// του κάθε αντικειμένου τύπου //Rectangle//. |
| {{ :cpp:cppstackheap.png | Σχηματικό διάγραμμα του stack και του heap της διεργασίας πριν, κατά τη διάρκεια και μετά την εκτέλεσης της συνάρτησης foo}} | {{ :cpp:cppstackheap.png | Σχηματικό διάγραμμα του stack και του heap της διεργασίας πριν, κατά τη διάρκεια και μετά την εκτέλεσης της συνάρτησης foo}} |
| |
| ===== Ένα πιο σύνθετο παράδειγμα αρχικοποίησης δεικτών ===== | Όταν δεν χρειαζόμαστε πλέον το αντικείμενο που δεσμεύτηκε δυναμικά στο //heap// θα πρέπει να το καταστρέψουμε ελευθερώνοντας τη δεσμευμένη μνήμη με τη βοήθεια του τελεστή //delete//. Κατά την απελευθέρωση της μνήμης μέσω του τελεστή //delete// καλείται ο καταστροφέας της κλάσης, σε αναλογία με την κλήση του κατασκευαστή της κλάσης με χρήση του τελεστή //new//. |
| | |
| | ===== 3η περίπτωση - δυναμικά δεσμευμένοι μονοδιάστατοι πίνακες από αντικείμενα ===== |
| |
| Παρακάτω δίνεται η κλάση //Rectangle// και ένα παράδειγμα αρχικοποίησης των τριών δεικτών //r1, r2, r3// τύπου //Rectangle//, οι οποίοι αρχικοποιούνται ως εξής: | Παρακάτω δίνεται η κλάση //Rectangle// και ένα παράδειγμα αρχικοποίησης των τριών δεικτών //r1, r2, r3// τύπου //Rectangle//, οι οποίοι αρχικοποιούνται ως εξής: |
| - ο δείκτης //r2// δείχνει σε ένα αντικείμενο που αρχικοποιείται στο //heap//. | - ο δείκτης //r2// δείχνει σε ένα αντικείμενο που αρχικοποιείται στο //heap//. |
| - ο δείκτης //r3// δείχνει σε ένα πίνακα από αντικείμενα που αρχικοποιείται επίσης στο //heap//. | - ο δείκτης //r3// δείχνει σε ένα πίνακα από αντικείμενα που αρχικοποιείται επίσης στο //heap//. |
| - ο δείκτης //r4// δείχνει σε ένα δισδιάστατο πίνακα από αντικείμενα που αρχικοποιείται επίσης στο //heap//. Ο πίνακας έχει δύο γραμμές και μία στήλη. | - πριν την ολοκλήρωση του προγράμματος πρέπει να ελευθερώσουμε τη μνήμη που δεσμεύτηκε στο //heap// κατά τη δημιουργία των αντικειμένων στα οποία δείχνουν οι δείκτες //r2, r3 και r4//. |
| - πριν την ολοκλήρωση του προγράμματος είμαστε υποχρεωμένοι να ελευθερώσουμε τη μνήμη που δεσμεύτηκε στο //heap// κατά τη δημιουργία των αντικειμένων στα οποία δείχνουν οι δείκτες //r2, r3 και r4//. | |
| |
| | <code cpp RectangleUsage-1.cpp> |
| <code cpp RectangleUsage1.cpp> | |
| #include <iostream> | #include <iostream> |
| using namespace std; | using namespace std; |
| </code> | </code> |
| |
| Μεταγλωττίστε και εκτελέστε τον παραπάνω κώδικα. Το output θα είναι το εξής: | Μεταγλωττίστε και εκτελέστε τον παραπάνω κώδικα. Η έξοδος θα είναι η εξής: |
| <code> | <code> |
| Calling 0 args constructor | Calling 0 args constructor |
| </code> | </code> |
| |
| | Παρατηρήστε ότι στον πίνακα //r3// πρώτα καταστρέφεται το αντικείμενο //r3[1]// και στη συνέχεια το αντικείμενο //r3[0]//. |
| ===== Ένα ακόμη πιο σύνθετο παράδειγμα αρχικοποίησης δεικτών ===== | ===== Ένα ακόμη πιο σύνθετο παράδειγμα αρχικοποίησης δεικτών ===== |
| |
| Παρακάτω δίνεται η κλάση //Rectangle// και ο δείκτης σε δείκτη τύπου //Rectangle// //r4//. Πριν την ολοκλήρωση του προγράμματος είμαστε και πάλι υποχρεωμένοι να ελευθερώσουμε τη μνήμη που δεσμεύτηκε στο //heap// κατά τη δημιουργία των αντικειμένων στα οποία δείχνουν οι ενδιάμεσοι δείκτες που δημιουργούνται και ο δείκτης //r4//. | Παρακάτω δίνεται η κλάση //Rectangle// και ο δείκτης σε δείκτη τύπου //Rectangle// //r4//, μέσω του οποίου δημιουργούμε ένα διδιάστατο πίνακα από ορθογώνια παραλληλόγραμμα. Η πρώτη γραμμή του πίνακα έχει δύο στήλες και η δεύτερη γραμμή τρεις στήλες. Πριν την ολοκλήρωση του προγράμματος είμαστε και πάλι υποχρεωμένοι να ελευθερώσουμε τη μνήμη που δεσμεύτηκε στο //heap// κατά τη δημιουργία των αντικειμένων στα οποία δείχνουν οι ενδιάμεσοι δείκτες που δημιουργούνται και ο δείκτης //r4//. |
| | |
| | <code cpp RectangleUsage-2.cpp> |
| | #include <iostream> |
| | using namespace std; |
| | #include "Rectangle.hpp" |
| | |
| | /* Δημιουργώ ένα δυναμικά δεσμευμένο |
| | * διδιάστατο πίνακα από αντικείμενα |
| | * τύπου Rectangle. |
| | */ |
| | |
| | int main() { |
| | |
| | Rectangle **r4; |
| | cout << "--- init r4 ---" << endl; |
| | r4 = new Rectangle*[2]; |
| | cout << "--- init r4[0] ---" << endl; |
| | r4[0] = new Rectangle[2] {{5,6}, {7,8}}; |
| | cout << "--- init r4[1] ---" << endl; |
| | r4[1] = new Rectangle[3] {{9}, {10}, {11,10}}; |
| | |
| | cout << "---------------" << endl; |
| | cout << "r4[0][0]'s getArea: " << r4[0][0].getArea() << endl; |
| | cout << "r4[0][1]'s getArea: " << r4[0][1].getArea() << endl; |
| | cout << "r4[1][0]'s getArea: " << r4[1][0].getArea() << endl; |
| | cout << "r4[1][1]'s getArea: " << r4[1][1].getArea() << endl; |
| | cout << "r4[1][2]'s getArea: " << r4[1][2].getArea() << endl; |
| | cout << "---------------" << endl; |
| | |
| | delete[] r4[0]; // Call the destructor of Rectangle for all elements in row 0. |
| | delete[] r4[1]; // Call the destructor of Rectangle for all elements in row 1. |
| | delete[] r4; |
| | } |
| | </code> |
| |
| |