Sunteți pe pagina 1din 8

Advance Tools and Techniques

Overloading new and delete


Specialized operators can give more flexibility in how
and when memory allocation and de-allocation occur

Run-Time Type Identification


Can obtain type specific information from an object
Can allow access to derived class methods and
members through a pointer/reference to a base class

Pointer to Class Member


Can be used to identify a data member or a member
function or operator within an object

CSE 332: C++ Advanced Tools and Techniques

Operators new and delete are Inverses


string *sp = new string ("a value");
string *arr = new string[10];

Three steps occur when new is called

A library function named operator new (or operator new[]) is called,


which allocates raw, untyped memory from the heap
Placement version of new is passed pointer to existing memory, and skips this step

The appropriate constructor(s) is(are) called to construct the object(s) from


the initializers
A pointer to the newly allocated and constructed object is returned as the
expressions value
delete sp;
delete [] arr;

Three steps occur when delete is called (inverse of for new)

A pointer to the memory to be de-allocated is passed as a parameter


A destructor is run at the position (version without []) or destructors are run
at all positions (version with []) to the parameter points
Memory is returned to the heap by calling library function operator delete
or operator delete[]

CSE 332: C++ Advanced Tools and Techniques

Interfaces for Operators new and delete


// might throw
void *operator
void *operator
void *operator
void *operator

an exception
new(size_t);
new[](size_t);
delete(void*) noexcept;
delete[](void*) noexcept;

// promise not
void *operator
void *operator
void *operator
void *operator

to throw
new(size_t, nothrow_t&) noexcept;
new[](size_t, nothrow_t&) noexcept;
delete(void*, nothrow_t&) noexcept;
delete[](void*, nothrow_t&) noexcept;

// placement new operators dont allocate: just call


// constructor(s) starting at passed address, return it
void *operator new(size_t, void*); // cant redefine
void *operator new[](size_t, void*);

CSE 332: C++ Advanced Tools and Techniques

Implementations of Operators new and delete


// From LLM pp. 823
void *operator new(size_t size) {
if (void *meme = malloc(size))
return meme;
else
throw bad_alloc();
}
void operator delete (void *meme) noexcept {
free (meme);
}

CSE 332: C++ Advanced Tools and Techniques

Run-Time Type Identification


The dynamic_cast operator returns a pointer or reference to a more specific
(derived) type if it can
Only can be used with pointers to structs or classes with virtual methods
The dynamic_cast operator returns nullptr (or throws an exception) if it cannot downcast
to the specified type
dynamic_cast<type*> (base) // returns a pointer
dynamic_cast<type&> (base) // returns an l-value reference
dynamic_cast<type&&> (base) // returns an r-value reference

The typeid operator returns a type_info for a given expression

Works with built-in types as well as user-declared types


Cannot declare or construct type_info objects explicitly
Can only use implicitly via expressions involving the typeid operator and operators and
methods available for type_info objects, e.g.,
cout << "e is of type " << typeid(e).name() << endl;
cout << " f is of type " << typeid(f).name() << endl;
cout << " the types are " <<
(typeid(e) == typeid(f) ? " " : " not ") <<
"the same" << endl;

CSE 332: C++ Advanced Tools and Techniques

Run-Time Type Identification Example


bool same_cage (Animal * a, Animal * b) {
// only ok if both are Pandas
return dynamic_cast<Panda *>(a) &&
dynamic_cast<Panda *>(b);
}

Output:
We have a struct Grizzly
and a struct Panda
Dont put in same cage!

int main (int, char * []) {


Animal *a = new Grizzly ();
Animal *b = new Panda ();
cout << "we have a "
<< typeid(*a).name() << endl << "and a "
<< typeid(*b).name() << endl << endl;
if (!same_cage(a, b)) {
cout << "Dont put in same cage!" << endl;
}
delete a; delete b;
return 0;
}

CSE 332: C++ Advanced Tools and Techniques

Pointer to Data Member


struct Truck {
Truck (unsigned int w): weight_(w) {
cout << "weight: " << weight_ << endl;}
unsigned int weight_;
};
int main (int, char * []) {
Truck trucks [] = {902, 900};
auto weight_ptr = &Truck::weight_; // data

Output:
weight: 902
weight: 900
Truck weights are:
Truck 0 weight is 902
Truck 1 weight is 900

cout << "Truck weights are: " << endl;


for (Truck* truck_ptr = trucks;
truck_ptr - trucks <
sizeof(trucks)/sizeof(Truck);
++truck_ptr) {
cout << "Truck " << truck_ptr - trucks
<< " weight is "
<< truck_ptr->*weight_ptr
<< endl;
}
return 0;
}

CSE 332: C++ Advanced Tools and Techniques

Pointer to Member Function


class Truck {
public:
Output:
Truck (unsigned int w): weight_(w) {
cout << "weight: " << weight_ << endl;}
weight: 902
unsigned int weight() {return weight_;}
weight: 900
private:
Truck weights are:
unsigned int weight_;
Truck 0 weight is 902
};
Truck 1 weight is 900
int main (int, char * []) {
Truck trucks [] = {902, 900};
// declaration almost identical to previous
auto weight_ptr = &Truck::weight; // fxn
cout << "Truck weights are: " << endl;
for (Truck* truck_ptr = trucks;
truck_ptr - trucks <
sizeof(trucks)/sizeof(Truck);
++truck_ptr) {
cout << "Truck " << truck_ptr - trucks
<< " weight is "
<< (truck_ptr->*weight_ptr)() << endl; // note how parens are used
}
return 0;
}

CSE 332: C++ Advanced Tools and Techniques

S-ar putea să vă placă și