====== Δυναμική διαχείριση μνήμης ====== Όπως και στη C έτσι και στη C++ η μνήμη μπορεί να δεσμευθεί δυναμικά στο χώρο δεδομένων που ονομάζεται //heap//. Εκτός των συναρτήσεων [[http://www.cplusplus.com/reference/cstdlib/malloc/|malloc]] και [[http://www.cplusplus.com/reference/cstdlib/free/|free]] που εξακολουθούν να υφίστανται και στη C++, ορίζονται οι τελεστές **new** και **delete** για δέσμευση και αποδέσμευση μνήμης. Δεν θα πρέπει να συγχέεται ποτέ η χρήση **malloc/free** με **new/delete** για τη δέσμευση και αποδέσμευση μνήμης. Οποιοσδήποτε χώρος δεν δεσμεύτηκε με //malloc// θα πρέπει να ελευθερωθεί με //free//. Αντίστοιχα ότι δεσμεύθηκε με //new// θα πρέπει να ελευθερωθεί με //delete//. Οι τελεστής **new** εκτός από τη δέσμευση μνήμης επιτρέπει και τη αρχικοποίηση μεταβλητών βασικού ή αναφορικού τύπου με χρήση του αντίστοιχου κατασκευαστή. Ο τελεστής **new** έχει δύο μορφές (**new** και **new[]**). Η πρώτη χρησιμοποιείται για την δέσμευση μνήμης ενός αντικειμένου ή μιας μεταβλητής βασικού τόπου, ενώ η δεύτερη για τη δέσμευση μνήμης και την αρχικοποίηση ενός πίνακα. Σε αναλογία με τον τελεστή **new** ο τελεστής **delete** για την αποδέσμευση μνήμης έχει και αυτός δύο μορφές (**delete** και **delete[]**). Η πρώτη χρησιμοποιείται για την αποδέσμευση μνήμης ενός αντικειμένου ή μιας μεταβλητής βασικού τϋπου, ενώ η δεύτερη για την αποδέσμευση μνήμης ενός πίνακα. Δείτε το παρακάτω παράδειγμα χρήσης των τελεστών **new** και **delete**. #include using namespace std; int main () { int *num, *p; num = new int; cout << "Enter number of elements: "; cin >> *num; p = new int[*num]; for(int i=0; i<*num; i++) { cout << "Next integer: "; cin >> p[i]; } for(int i=0; i<*num; i++) { cout << p[i] << "\t"; } cout << endl; delete []p; delete num; } Για βασικούς τύπους δεδομένων μπορείτε να αρχικοποιήσετε τη μεταβλητή ως εξής, με χρήση του τελεστή **new**: #include using namespace std; int main () { int *num_ptr; num_ptr = new int(5); // δέσμευση μνήμης και ανάθεση της τιμής 5 // στο περιεχόμενο της διεύθυνσης αυτής. cout << "num: " << num_ptr; } ===== Έλεγχος δέσμευσης μνήμης ===== Κατά τη δέσμευση μνήμης δεν είναι απαραίτητο να γίνονται οι έλεγχοι για το κατά πόσο η δέσμευση απέτυχε. Στην περίπτωση που η δέσμευση μνήμης αποτύχει τότε παράγεται ένα //exception// τύπου ''bad_alloc'' το οποίο καλούμαστε να διαχειριστούμε, διαφορετικά το πρόγραμμα θα τερματίσει. Εάν δεν επιθυμούμε ο τελεστής **new** να παράξει //exception//, θα πρέπει να αλλάξουμε τον τρόπο κλήσης προσθέτοντας τη δεσμευμένη έκφραση ''(nothrow)'' αμέσως μετά τον τελεστή **new** και να ελέγξουμε την επιστρεφόμενη τιμή ως εξής: #include using namespace std; int main () { int *num, *p; num = new int; cout << "Enter number of elements: "; cin >> *num; p = new (nothrow) int[*num]; if(p==NULL) { cout << "Allocation failure!\n"; return 0; } for(int i=0; i<*num; i++) { cout << "Next integer: "; cin >> p[i]; } for(int i=0; i<*num; i++) { cout << p[i] << "\t"; } cout << endl; delete []p; delete num; } ===== Παράδειγμα δέσμευσης μνήμης για την αρχικοποίηση ενός διδιάστατου πίνακα ===== #include #include using namespace std; int main(int argc, char *argv[]) { int **array2d, rows, columns; cout << "Enter number of rows: "; cin >> rows; cout << "Enter number of columns: "; cin >> columns; array2d = new (nothrow) int*[rows]; if(array2d == NULL) { cerr < "Memory allocation error!\n"; return -1; } for(int i=0; i