Αναφορές και Δυναμική Μνήμη

Προγραμματισμός Ι
Πίνακες, Δείκτες, Αναφορές και Δυναμική Μνήμη
Δημήτρης Μιχαήλ
Τμήμα Πληροφορικής και Τηλεματικής
Χαροκόπειο Πανεπιστήμιο
Πίνακες Αντικειμένων
Όπως στην C μπορούμε να έχουμε πίνακες από δομές, έτσι και στην C++
μπορούμε να έχουμε πίνακες αντικειμένων.
1
2
3
4
5
6
class cl {
int param ;
public :
cl ( int j ) { param = j ; }
int getParam ( ) { return param ; }
};
7
8
9
int main ( ) {
cl ob [ 3 ] = { cl ( 1 ) , cl ( 2 ) , cl ( 3 ) } ;
//
initializers
10
for ( int i = 0 ; i < 3 ; i++)
cout << ob [ i ] . getParam ( ) << endl ;
11
12
13
}
Παραπάνω φαίνεται επίσης πως καλούμε τους constructors κάθε
αντικειμένου. Για να μην δώσετε και τους initializers πρέπει η κλάση να
παρέχει ένα constructor που να μην δέχεται παραμέτρους.
Χαροκόπειο Πανεπιστήμιο
2/50
Δείκτες Αντικειμένων
Όπως έχουμε δείκτες σε άλλους τύπους μεταβλητών, μπορούμε να έχουμε
και δείκτες σε αντικείμενα.
Όπως και στις εγγραφές για να προσπελάσουμε τα μέλη ενός αντικειμένου
μέσω ενός δείκτη πρέπει να χρησιμοποιήσουμε τον τελεστή βέλους (->).
1
2
3
4
5
6
class cl {
int param ;
public :
cl ( int j ) { param = j ; }
int getParam ( ) { return param ; }
};
7
8
9
int main ( ) {
cl ob ( 8 8 ) , * p ;
10
p = &ob ;
11
12
cout << p−>getParam ( ) << endl ;
13
14
}
Χαροκόπειο Πανεπιστήμιο
3/50
Ο δείκτης this
Όταν μια συνάρτηση μέλος μια κλάσης καλείται σε ένα αντικείμενο, έχει
αυτόματη πρόσβαση σε ένα δείκτη this που δείχνει στο αντικείμενο αυτό.
1
2
3
4
5
6
7
8
9
10
class cl {
int param ;
public :
cl ( int j ) {
this−>param = j ;
}
int getParam ( ) {
return this−>param ;
}
};
Στην παραπάνω περίπτωση η χρήση αυτή δεν είναι απαραίτητη και μπορεί
να παραληφθεί ο δείκτης this. Υπάρχουν όμως περιπτώσεις όπου ο
δείκτης αυτός είναι πολύ χρήσιμος.
Χαροκόπειο Πανεπιστήμιο
4/50
Αναφορές
Η C++ μας παρέχει την έννοια των αναφορών που χρησιμοποιείται σε 3
περιπτώσεις:
1.
ως παράμετρος σε συνάρτηση
2.
ως τύπος επιστροφής από συνάρτηση
3.
ως ανεξάρτητη αναφορά
Χαροκόπειο Πανεπιστήμιο
5/50
Κλήση μέσω Αναφοράς
Η πιο σημαντική εφαρμογή των αναφορών είναι μάλλον η δυνατότητα να
δημιουργήσουμε συναρτήσεις που χρησιμοποιούν αυτόματα "κλήση μέσω
αναφοράς".
11
12
13
void neg ( int &i ) {
i = −i ;
}
14
15
16
int main ( ) {
int x = 1 0 ;
17
cout << x << "␣negated␣is␣" ;
18
19
neg ( x ) ;
20
21
cout << x << endl ;
22
23
}
Χαροκόπειο Πανεπιστήμιο
6/50
Κλήση μέσω Αναφοράς
Η πιο σημαντική εφαρμογή των αναφορών είναι μάλλον η δυνατότητα να
δημιουργήσουμε συναρτήσεις που χρησιμοποιούν αυτόματα "κλήση μέσω
αναφοράς".
24
25
26
27
28
void swap ( int &x , int &y ) {
int tmp = x ;
x = y;
y = tmp ;
}
29
30
31
int main ( ) {
int x = 10 , y = 2 0 ;
32
swap ( x , y ) ;
33
34
cout << "x␣=␣" << x << ",␣y␣=␣" << y << endl ;
35
36
}
Χαροκόπειο Πανεπιστήμιο
7/50
Αντικείμενα ως Παράμετροι
Εαν καλέσουμε μια συνάρτηση με παράμετρο ένα αντικείμενο,
δημιουργείται ένα αντίγραφο του αντικειμένου. Στο τέλος της συνάρτησης
το αντίγραφο αυτό καταστρέφεται κανονικά.
class cl {
int id ;
public :
cl ( int i ) {
id = i ;
cout << "Constructing␣id␣=␣" << id << endl ;
}
~cl ( ) {
cout << "Destructing␣id␣=␣" << id << endl ;
}
};
void print ( cl o )
{ }
void print1 ( cl& o ) { }
/ / no r e f e r e n c e , copy
/ / r e f e r e n c e , no copy
int main ( ) {
cl obj ( 2 ) ;
print ( obj ) ;
print1 ( obj ) ;
}
Χαροκόπειο Πανεπιστήμιο
8/50
Αντικείμενα ως Παράμετροι
Με την χρήση αναφοράς δεν δημιουργείται αντίγραφο.
class cl {
int id ;
public :
cl ( int i ) {
id = i ;
cout << "Constructing␣id␣=␣" << id << endl ;
}
~cl ( ) {
cout << "Destructing␣id␣=␣" << id << endl ;
}
};
void print ( cl o )
{ }
void print1 ( cl& o ) { }
/ / no r e f e r e n c e , copy
/ / r e f e r e n c e , no copy
int main ( ) {
cl obj ( 2 ) ;
print ( obj ) ;
print1 ( obj ) ;
}
Χαροκόπειο Πανεπιστήμιο
8/50
Αναφορές ως Τύπος Επιστροφής Συνάρτησης
Μια συνάρτηση μπορεί να επιστρέψει αναφορά.
Το παράξενο γεγονός είναι πως με αυτόν τον τρόπο μπορεί μια συνάρτηση
να χρησιμοποιηθεί στην αριστερή πλευρά μιας ανάθεσης.
Πρέπει όμως πάντα να προσέχουμε πως η αναφορά πρέπει να αναφέρεται
σε ένα αντικείμενο που δεν βγαίνει εκτός scope με το τέλος της
συνάρτησης.
Χαροκόπειο Πανεπιστήμιο
9/50
Αναφορές ως Τύπος Επιστροφής Συνάρτησης
Μια συνάρτηση μπορεί να επιστρέψει αναφορά.
#include < i o s t r e a m >
using namespace std ;
char s [ 8 0 ] = "Hello␣There" ;
char& replace ( int i )
{
return s [ i ] ;
}
/ / return a reference
int main ( ) {
replace ( 5 ) = 'X' ;
cout << s << endl ;
}
Χαροκόπειο Πανεπιστήμιο
10/50
Ανεξάρτητες Αναφορές
Μπορούμε να δημιουργήσουμε ανεξάρτητες αναφορές, οι οποίες είναι απλά
ψευδώνυμα για άλλες μεταβλητές.
int main ( ) {
int a ;
int &ref = a ;
/ / independent r e f e r e n c e
a = 10;
cout << a << "␣" << ref << endl ;
ref = 100;
cout << a << "␣" << ref << endl ;
int b = 1 9 ;
ref = b ;
/ / put b ' s value of i n t o a
cout << a << "␣" << ref << endl ;
ref−−;
ref−−;
/ / decrement a
/ / again
cout << a << "␣" << ref << endl ;
}
Χαροκόπειο Πανεπιστήμιο
11/50
Δυναμική Μνήμη στην C++
Η C++ παρέχει δύο τελεστές για δυναμική δέσμευση μνήμης: new και
delete.
Για λόγους συμβατότητας η C++ υποστηρίζει και τις συναρτήσεις malloc()
και free().
Είναι προτιμότερο όμως να χρησιμοποιούμε την μέθοδο της C++ για
δέσμευση και ελευθέρωση δυναμικής μνήμης.
Χαροκόπειο Πανεπιστήμιο
12/50
Δυναμική Μνήμη
Ο τελεστής new δεσμεύει μνήμη και χρησιμοποιείται ως εξής:
p_var = new type;
Εδώ p_var είναι μια μεταβλητή τύπου δείκτη.
Αντίστοιχα η διαγραφή της μνήμης γίνεται με τον τελεστή delete.
delete p_var;
Χαροκόπειο Πανεπιστήμιο
13/50
Δυναμική Μνήμη
Παράδειγμα
class complex {
double a , b ;
public :
complex ( ) { this−>a = 0 . 0 ; this−>b = 0 . 0 ; }
complex ( double a , double b ) { this−>a = a ; this−>b = b ; }
~complex ( ) ;
double re ( ) { return a ; }
double im ( ) { return b ; }
};
int main ( ) {
complex * c = new complex ;
/ / do something
delete c ;
}
Χαροκόπειο Πανεπιστήμιο
14/50
Πλεονεκτήματα new σε σχέση με malloc
1.
η new αυτόματα δεσμεύει τον απαραίτητο χώρο για την αποθήκευση
ενός τύπου χωρίς να χρειάζεται να δώσουμε το μέγεθος του τύπου
μέσω του τελεστή sizeof.
2.
η new επιστρέφει ένα δείκτη στον τύπο που ζητήσαμε και άρα δεν
χρειάζεται να γίνει κάποιο cast.
3.
οι τελεστές new και delete μπορούν να υπερφορτωθούν ώστε να
δημιουργήσουμε δικά μας συστήματα δέσμευσης μνήμης.
Χαροκόπειο Πανεπιστήμιο
15/50
Αρχικοποίηση Δυναμικής Μνήμης
Μπορούμε να αρχικοποιήσουμε την δεσμευμένη μνήμη με κάποια τιμή.
Πρέπει βέβαια να υπάρχει και constructor που να υποστηρίζει αυτήν την τιμή.
int main ( ) {
complex * c = new complex ( 2 , 5 ) ;
/ / do something
delete c ;
}
Χαροκόπειο Πανεπιστήμιο
16/50
Αρχικοποίηση Δυναμικής Μνήμης
Μπορούμε να αρχικοποιήσουμε την δεσμευμένη μνήμη με κάποια τιμή.
int main ( ) {
int * d = new int ( 5 ) ;
//
i n i t i a l i z e to 5
/ / do something
delete d ;
}
Χαροκόπειο Πανεπιστήμιο
17/50
Δυναμικοί Πίνακες
Για να δεσμεύσουμε μνήμη δυναμικά για πίνακες χρησιμοποιούμε την γενική
μορφή:
p_var = new array_type [size];
και για να διαγράψουμε την μνήμη του πίνακα:
delete [] pvar;
Χαροκόπειο Πανεπιστήμιο
18/50
Δυναμικοί Πίνακες
#include < i o s t r e a m >
using namespace std ;
int main ( ) {
int * p = new int [ 1 0 ] ;
for ( int i = 0 ; i < 1 0 ; i++)
p[i] = i;
for ( int i = 0 ; i < 1 0 ; i++)
cout << p [ i ] << "␣" ;
delete [ ] p ;
}
Όταν δεσμεύουμε δυναμικά πίνακες, υπάρχει ο περιορισμός πως δεν
μπορούμε να δώσουμε αρχικές τιμές. Αυτό σημαίνει πως αν θέλουμε ένα
δυναμικό πίνακα με αντικείμενα, πρέπει η αντίστοιχη κλάση να περιέχει
έναν constructor χωρίς παραμέτρους.
Χαροκόπειο Πανεπιστήμιο
19/50
Έλεγχος Επιτυχής Δέσμευσης
Εξαιρέσεις
Η C++ χρησιμοποιεί ένα καινούριο μηχανισμό για να μας ενημερώσει πως η
δέσμευση μνήμης δεν ήταν επιτυχής, τις εξαιρέσεις.
θα κάνουμε μια μικρή παρένθεση ώστε να εξηγήσουμε λίγο την έννοια των
εξαιρέσεων.
Χαροκόπειο Πανεπιστήμιο
20/50
Εξαιρέσεις
Exceptions
Οι εξαιρέσεις είναι ένας σύγχρονως τρόπος ενημέρωσης για λάθοι.
Στην C++ η διαχείριση εξαιρέσεων χρησιμοποιεί 3 δεσμευμένες λέξεις:
• try
• catch
• throw
Χαροκόπειο Πανεπιστήμιο
21/50
Εξαιρέσεις
Exceptions
Στην C++ η διαχείριση εξαιρέσεων χρησιμοποιεί 3 δεσμευμένες λέξεις:
• συνήθως οι εντολές που θέλουμε να παρακολουθούμε για εξαιρέσεις
εκτελούνται μέσα σε ένα try block.
• εάν μια εξαίρεση (ένα λάθος) συμβεί μέσα στο try block, λέμε πως
πετάχτηκε μια εξαίρεση (με την χρήση της throw).
• η εξαίρεση πιάνετε με την χρήση της catch
Χαροκόπειο Πανεπιστήμιο
22/50
Γενική Μορφή try
try {
//
}
catch(
//
}
catch(
//
}
...
catch(
//
}
Χαροκόπειο Πανεπιστήμιο
try block
type1 arg ) {
catch block
type2 arg ) {
catch block
typeN arg ) {
catch block
23/50
Γενική Μορφή try
Όταν μια εξαίρεση πεταχτεί μέσα στο try block, πιάνεται από το αντίστοιχο
catch block που εκτελεί κώδικα ώστε να διαχειριστεί την εξαίρεση.
Πιο catch block θα εκτελεστεί εξαρτάται από τον τύπο της εξαίρεσης. Ο
τύπος μπορεί να είναι οποιοσδήποτε, ακόμη και κλάσης που έχετε φτιάξει
εσείς.
Εαν ο κώδικας δεν πετάξει καμία εξαίρεση, δεν εκτελείται κανένα catch.
Χαροκόπειο Πανεπιστήμιο
24/50
Γενική Μορφή throw
throw exception;
Εαν μια εξαίρεση πρέπει να πιαστεί, το throw πρέπει να κληθεί μέσα σε ένα
try, ή μέσα σε μια συνάρτηση που κλήθηκε μέσε σε ένα try.
Εαν δεν υπάρχει αντίστοιχο catch για τον τύπο της εξαίρεσης τότε το
πρόγραμμα τερματίζει. Η τυπική βιβλιοθήκη καλεί την συνάρτηση
terminate() η οποία με την σειρά της καλεί την συνάρτηση abort().
Υπάρχει βέβαια η δυνατότητα να αλλάξετε αυτή την διαδικασία και να
καλέσετε δικιά σας συνάρτηση.
Χαροκόπειο Πανεπιστήμιο
25/50
Παράδειγμα
#include < i o s t r e a m >
using namespace std ;
int main ( ) {
cout << "Start" << endl ;
try {
cout << "Inside␣try␣block" << endl ;
throw 100;
cout << "This␣will␣not␣execute" << endl ;
}
catch ( int i ) {
/ / catch exception of type i n t
cout << "Caught␣an␣exception␣--␣value␣is␣" << i << endl ;
}
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
26/50
Παράδειγμα
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Inside try block
Caught an exception -- value is 100
End
Χαροκόπειο Πανεπιστήμιο
27/50
Παράδειγμα
Εαν πετάξουμε εξαίρεση που δεν υπάρχει αντίστοιχο catch, π.χ μια
εξαίρεση τύπου double
#include < i o s t r e a m >
using namespace std ;
int main ( ) {
cout << "Start" << endl ;
try {
cout << "Inside␣try␣block" << endl ;
throw 1 0 0 . 0 ;
cout << "This␣will␣not␣execute" << endl ;
}
catch ( int i ) {
/ / catch exception of type i n t
cout << "Caught␣an␣exception␣--␣value␣is␣" << i << endl ;
}
cout << "End" << endl ;
}
το πρόγραμμα θα τερματίσει.
Χαροκόπειο Πανεπιστήμιο
28/50
Παράδειγμα
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Inside try block
terminate called after throwing an instance of 'double'
Aborted
Χαροκόπειο Πανεπιστήμιο
29/50
Εξαιρέσεις μέσα σε συναρτήσεις
#include < i o s t r e a m >
using namespace std ;
void Xhandler ( int test ) {
try {
if ( test )
throw test ;
}
catch ( int i ) {
cout << "Caught␣Exception␣#:␣" << i << endl ;
}
}
int main ( ) {
cout << "Start" << endl ;
Xhandler ( 1 ) ;
Xhandler ( 2 ) ;
Xhandler ( 0 ) ;
Xhandler ( 3 ) ;
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
30/50
Εξαιρέσεις μέσα σε συναρτήσεις
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Caught Exception #: 1
Caught Exception #: 2
Caught Exception #: 3
End
Χαροκόπειο Πανεπιστήμιο
31/50
Εξαιρέσεις μέσα σε συναρτήσεις
#include < i o s t r e a m >
using namespace std ;
void Xtest ( int test ) {
cout << "Inside␣Xtest,␣test␣is:␣" << test << endl ;
if ( test )
throw test ;
}
int main ( ) {
cout << "Start" << endl ;
try {
cout << "Inside␣try␣block" << endl ;
Xtest ( 0 ) ;
Xtest ( 1 ) ;
Xtest ( 2 ) ;
}
catch ( int i ) {
cout << "Caught␣an␣exception␣--␣value␣is␣" << i << endl ;
}
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
32/50
Εξαιρέσεις μέσα σε συναρτήσεις
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Inside
Inside
Inside
Caught
End
try block
Xtest, test is: 0
Xtest, test is: 1
an exception -- value is 1
Χαροκόπειο Πανεπιστήμιο
33/50
Πιάνοντας Κλάσεις
Μια εξαίρεση μπορεί να είναι οποιαδήποτε τύπου. Σε πραγματικά
προγράμματα οι εξαιρέσεις είναι συνήθως κάποια κλάση.
#include < i o s t r e a m >
#include < c s t r i n g >
using namespace std ;
class MyException {
char str_what [ 8 0 ] ;
int what ;
public :
MyException ( ) { * str_what = 0 ; what = 0 ; }
MyException ( char * s , int e ) {
strcpy ( str_what , s ) ;
what = e ;
}
int What ( ) { return what ; }
char * StrWhat ( ) { return str_wat ; }
}
Χαροκόπειο Πανεπιστήμιο
34/50
Πιάνοντας Κλάσεις
Μια εξαίρεση μπορεί να είναι οποιαδήποτε τύπου. Σε πραγματικά
προγράμματα οι εξαιρέσεις είναι συνήθως κάποια κλάση.
int main ( ) {
int i ;
try {
cout << "Enter␣a␣positive␣number:␣" ;
cin >> i ;
if ( i < 0 )
throw MyException ( "Not␣Positive" , i ) ;
}
catch ( MyException e ) {
cout << e . Str_What ( ) << ":␣" << e . What ( ) << endl ;
}
}
Enter a positive number: -4
Not Positive: -4
Χαροκόπειο Πανεπιστήμιο
35/50
Πολλά catch
#include < i o s t r e a m >
using namespace std ;
void Xhandler ( int test ) {
try {
if ( test ) throw test ;
else throw "Value␣is␣zero" ;
}
catch ( int i ) {
cout << "Caught␣Exception␣#:␣" << i << endl ;
}
catch ( const char * str ) {
cout << "Caught␣a␣string:␣" << str << endl ;
}
}
int main ( ) {
cout << "Start" << endl ;
Xhandler ( 1 ) ;
Xhandler ( 2 ) ;
Xhandler ( 0 ) ;
Xhandler ( 3 ) ;
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
36/50
Πολλά catch
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Caught
Caught
Caught
Caught
End
Exception
Exception
a string:
Exception
Χαροκόπειο Πανεπιστήμιο
#: 1
#: 2
Value is zero
#: 3
37/50
Πιάνοντας όλες τις Εξαιρέσεις
Για να γράψουμε ένα catch που να πιάνει τα πάντα μπορούμε να
χρησιμοποιήσουμε την εξής μορφή:
catch(...) {
// process all exceptions
}
Χαροκόπειο Πανεπιστήμιο
38/50
Πιάνοντας όλες τις Εξαιρέσεις
#include < i o s t r e a m >
using namespace std ;
void Xhandler ( int test ) {
try {
if ( test == 0 ) throw test ;
if ( test == 1 ) throw 'a' ;
if ( test == 2 ) throw 1 . 3 3 ;
}
catch ( . . . ) {
cout << "Caught␣Exception!" << endl ;
}
}
int main ( ) {
cout << "Start" << endl ;
Xhandler ( 0 ) ;
Xhandler ( 1 ) ;
Xhandler ( 2 ) ;
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
39/50
Πιάνοντας όλες τις Εξαιρέσεις
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Caught Exception!
Caught Exception!
Caught Exception!
End
Χαροκόπειο Πανεπιστήμιο
40/50
Πιάνοντας όλες τις Εξαιρέσεις
#include < i o s t r e a m >
using namespace std ;
void Xhandler ( int test ) {
try {
if ( test == 0 ) throw test ;
if ( test == 1 ) throw 'a' ;
if ( test == 2 ) throw 1 . 3 3 ;
}
catch ( int i ) {
cout << "Caught␣an␣integer" << endl ;
}
catch ( . . . ) {
cout << "Caught␣Other␣Exception!" << endl ;
}
}
int main ( ) {
cout << "Start" << endl ;
Xhandler ( 0 ) ;
Xhandler ( 1 ) ;
Xhandler ( 2 ) ;
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
41/50
Πιάνοντας όλες τις Εξαιρέσεις
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Caught an integer
Caught Other Exception!
Caught Other Exception!
End
Χαροκόπειο Πανεπιστήμιο
42/50
Προσδιορίζοντας τις Εξαιρέσεις
Μπορούμε να δηλώσουμε ρητά τους τύπους των εξαιρέσεων που μπορεί να
πετάξει μια συνάρτηση.
ret-type func-name(arg-list) throw(type-list)
{
//...
}
Εαν η συνάρτηση πετάξει οτιδήποτε που δεν ανήκει στην λίστα αυτή, η
συνάρτηση unexpected() της τυπικής βιβλιοθήκης θα κληθεί.
Η συνάρτηση αυτή όπως και η terminate() καλεί την abort(). Είναι όμως
δυνατόν να αλλάξουμε αυτή την συμπεριφορά.
Χαροκόπειο Πανεπιστήμιο
43/50
Επαναπέταγμα μιας Εξαίρεσης
Μέσα σε ένα catch block μπορούμε να επαναπετάξουμε μια εξαίρεση. Αυτό
είναι χρήσιμο εαν θέλουμε να διαχειριστούμε ένα λάθος τμηματικά.
Για να συμβεί αυτό καλούμε την throw χωρίς παραμέτρους.
Η εξαίρεση δεν θα πιαστεί από το ίδιο catch.
Χαροκόπειο Πανεπιστήμιο
44/50
Επαναπέταγμα μιας Εξαίρεσης
#include < i o s t r e a m >
using namespace std ;
void Xhandler ( ) {
try {
throw "hello" ;
}
catch ( const char * ) {
cout << "Caught␣char␣*␣inside␣Xhandler" << endl ;
throw ;
/ / rethrow out of f u n c t i o n
}
}
int main ( ) {
cout << "Start" << endl ;
try {
Xhandler ( ) ;
}
catch ( const char * ) {
cout << "Caught␣char␣*␣inside␣main" << endl ;
}
cout << "End" << endl ;
}
Χαροκόπειο Πανεπιστήμιο
45/50
Επαναπέταγμα μιας Εξαίρεσης
Το προηγούμενο πρόγραμμα τυπώνει:
Start
Caught char * inside Xhandler
Caught char * inside main
End
Χαροκόπειο Πανεπιστήμιο
46/50
Επιστροφή στην Δυναμική Μνήμη
Εξαίρεση bad_alloc
Εαν για κάποιο λόγο δεν βρεθεί ο απαραίτητος χώρος που ζητήθηκε με την
χρήση της new, η new πετάει την εξαίρεση bad_alloc.
Η εξαίρεση αυτή είναι ορισμένη στο αρχείο επικεφαλίδας <new>.
Χαροκόπειο Πανεπιστήμιο
47/50
Εξαίρεση bad_alloc
#include < i o s t r e a m >
#include <new>
using namespace std ;
int main ( ) {
int * p ;
try {
p = new int ;
}
catch ( bad_alloc xa ) {
cout << "Allocation␣failure" << endl ;
return 1 ;
}
* p = 100;
cout << "At␣" << p << "␣is␣the␣value␣" << * p << endl ;
delete p ;
}
Χαροκόπειο Πανεπιστήμιο
48/50
Η Επιλογή nothrow
Για να παρέχει η C++ πιο εύκολη μετάβαση από την C μας παρέχει και μια
μορφή της new η οποία επιστρέφει null όταν η δέσμευση μνήμης αποτύχει.
p_var = new(nothrow) type;
Για την χρήση αυτής της μορφής πρέπει να κάνετε include το αρχείο
επικεφαλίδας <new>.
Χαροκόπειο Πανεπιστήμιο
49/50
Η Επιλογή nothrow
#include < i o s t r e a m >
#include <new>
using namespace std ;
int main ( ) {
int * p ;
p = new ( nothrow ) int ;
if ( ! p ) {
cout << "Allocation␣failure" << endl ;
return 1 ;
}
* p = 100;
cout << "At␣" << p << "␣is␣the␣value␣" << * p << endl ;
delete p ;
}
Χαροκόπειο Πανεπιστήμιο
50/50