190 likes | 202 Views
Learn about variables, pointers, dynamic memory allocation, memory leaks, arrays, and pointers in functions. Includes examples and explanations.
E N D
Pointers Revisited • What is a variable address, name, value? • What is a pointer? • How is a pointer declared? • What are the address-of (reference) and dereference operators? • How can a pointer be assigned a value? • How can a value of a memory location referred to by a pointer be accessed? • What is a constant pointer? What is a pointer to a constant? How are they declared? • What is the relationship between an array name and a pointer? • What is the operation to move a pointer to the next/previous memory location? • What is a null pointer? What is the loose/dangling pointer problem? • Can pointers be used with objects? How can a method be invoked on an object using a pointer? • what is the -> operator?
Why Dynamic Memory • when a variable is declared - a certain memory area (sufficient to hold the variable of this type or class) is allocated • not all memory can be allocated or efficiently allocated at compilation time • we are manipulating a set of data of arbitrary size • what if we allocate an array that is too small? • what if we allocate an array that is too large? • dynamicmemory allocation – memory allocation at execution time under the direct control of the programmer • dynamic memory allocation is more flexible since the program can claim and release memory as needed and potentially can get as much memory as the computer resources allow • heap - the system structure where the memory is allocated • The heap is separate for every program and is removed when the program finishes
new and delete • new and delete - operations used to dynamically manipulate memory • new - allocates a nameless variable of specified type (or class) and returns a pointer to it int *ip; // declare pointer ip = new int; // ip points to integer var • note that the variable has no name and the only way to access the variable is through the pointer ip: cin >> *ip; *ip += 20; cout << *ip; • new may take a parameter to initialize the variable with ip = new int(5); // 5 assigned to the var • delete - releases memory back to the heap so that it can be reused delete ip; • note - the memory pointed to by ip goes away not the pointer variable itself • Note memory allocation types • static variable/constant – location known at compile time: literal constants, global variables, allocated in special place for static vars. • automatic variable – with scope: local variables, parameters, temp. variables, allocated on stack • dynamic variable - created with new,allocated in heap
Memory Leak Problem • note that the pointer that points to the dynamic variable is the only way to access this variable • if the pointer is reassigned the dynamic variable is “lost”. This is called a memory leak problem int *ptr = new int; ptr = new int; // ERROR - memory leak • is this a memory leak? int *ptr1,*ptr2 = new int; ptr1=ptr2; ptr2 = new int; • does this code have a problem? int *ptr = new int; delete ptr; *ptr=5;
Pointers and Arrays • array name is equivalent to: base_type * const • that is array name is a pointer that cannot be changed • the array name points to the first element of the array • the array name can be used as a pointer • a pointer can be used as an array name int a[10], *p1, *p2; p1=a; // where does p1 point now? p1[2]=5; // which element does p1 access a=p2; // is this legal? p1[20]; // is this legal?
Dynamic Arrays • arrays can be created dynamically just as scalar variables. • new has to be passed the number of elements of the array int *p1, p2, num; p1=new int[10]; • the number of array elements need not be constant: cin >> num; p2=new int[num]; p2= new int[0]; // operates correctly, sometimes useful • new returns the pointer to the first element of the dynamically allocated array. This pointer can be used just like a regular array name: p1[2]=42; • note, unlike regular array names this pointer can still be changed p1=p2; • delete has special syntax for array deallocation: delete [] p1; • note that the pointer passed to delete does not have to be the same that receives the value returned by new • how does the computer know how many elements to delete? - part of dynamic array implementation
Pointers and Functions • Pointers can be passed as parameters to and returned by functions // passing pointer by value void funcVal(int *p){ *p = 22; p = new int(33); } // passing pointer by reference void funcRef(int * &p){ *p = 44; p = new int(55); } // passing pointer to pointer, superseded by above: seldom used void funcRefRef(int **pp){ **pp = 66; *pp = new int(77); } // returning pointer int *funcRet(void){ int *tmp = new int(88); return tmp; }
0 1 2 3 4 p these locations cannot be accessed by the program 0 1 2 3 4 p — — — — — Memory Leaks with Dynamic Arrays int *p = new int [5]; for (int i = 0; i < 5; ++i) p[i] = i; p = new int [5];
Dynamic Objects • objects can be allocated dynamically class myclass { public: myclass(int n){data=n;}; int getdata(void) const {return data;}; private: int data; }; • the object of class myclass can be allocated as follows: myclass *mp1; mp1 = new myclass(5); • when new is passed parameter - constructor is invoked • the object can then be used as regular object: cout << mp1->getdata(); • and destroyed: delete mp1;
Objects Containing Dynamic Members • if we want to create an object that can shrink and grow as needed? class yourclass { public: yourclass(int); private: int *d, size; }; • with the following constructor: yourclass::yourclass (int n){ d = new int[n]; size=n; } • then the following declaration yourclass yrobj(5); creates an object containing an array of 10 integer variables yourclass yrobj2(10); // 10-element array
Destructor • what do you think this statement does? delete yp1; • it deallocates the object leaking the array • destructor is a function that is called (automatically) when object goes out of scope class yourclass { public: yourclass(int); ~yourclass(void); private: int *d, size; }; • name of destructor - tilde (~) and name of class yourclass::~yourclass (void){ delete [] d; } • no need to deallocate automatic variables • destructor is never called explicitly and does not accept parameters • note that destructor is called on every local object when function finishes
Copy Constructor • what if we have this function (note that the object is passed by value): void myfunc (yourclass); • if we invoke it as follows myfunc(yrobj); What happens? • the function is passed a reference to the same array - copy of the array is not created • copy constructor is invoked automatically when a new copy of an object is implicitly created • when function returns an object • when function is passed an object by value • copy constructor can be used explicitly • copy constructor is not called when one object is assigned to another (more on that later)
Copy Constructor (cont.) • copy constructor is a constructor that accepts an object of the same class passed by reference class yourclass { public: yourclass(int); yourclass(const yourclass&); // copy constructor ~yourclass(void); private: int *d; int size; }; • defined as follows yourclass::yourclass (const yourclass& n){ size=n.size; d=new int[size]; for (int i=0; i < size; ++i) d[i]=n.d[i]; } • note that copy constructor can access private members of the parameter object • can be invoked explicitly as follows: yourclass(yrobj);
Assignment Overloading • what do you think this operation does? yrobj2=yrobj; • copies the value of the pointer leaking the array of the old object and not creating a copy of the array in the new object • assignment needs to be overloaded • assignment overloading operator accepts by reference the object on the right-hand-side of equation and is invoked by the object on the left-hand-side class yourclass { public: ... void operator= (const yourclass&); private: int *d; int size; }; • can define as follows (not quite right yet): void yourclass::operator= (const yourclass& rhs){ size=rhs.size; delete [] d; d=new int[size]; for (int i=0; i < size; ++i) d[i]=rhs.d[i]; }
Self-Assignment Protection • what happens if you do this assignment? yrobj=yrobj;It is legal in C++. Is our overloaded assignment going to handle it right? • this is a reserved keyword. It is a pointer to the object that invokes the member function. It is passed implicitly to every member function • assignment overloading (still not quite right): void yourclass::operator = (const yourclass &rhs){ if (this != &rhs){ // if not same size=rhs.size; delete [] d; d=new int[size]; for (int i=0; i < size; ++i) d[i]=rhs.d[i]; } }
Stackable Assignment • what happens if you do this assignment? yrobj3=yrobj2=yrobj; • here is the definition that gets above code to work correctly yourclass& yourclass::operator = (const yourclass& rhs){ if (this != &rhs){ // if not same size=rhs.size; delete [] d; d=new int[size]; for (int i=0; i < size; i++) d[i]=rhs.d[i]; } return *this; // return lhs } • note the return value of the function, it is a reference to an object • returned object refers to object used in return-statement • similar to pass-by-reference parameter • seldom used t in C++, more common in pointerless-languages (Java, C#)
The BIG Three • big three - copy constructor, overloaded assignment and destructor • expert opinion - if you need any one of them - most probably you will need all three • they are not syntactically related but it is usually safer to define all three if you think you’d need at least one
Dynamic Memory Review • What are static, automatic, dynamic variables? Why are dynamic(ally allocated) variables needed? • What is program stack? Function (invocation) frame? • What is a heap? how is it used? • What are the new and delete operations? How are they used? • How does one access a dynamically allocated variable? How does one assign a value to such a variable at declaration time? • What is a memory leak? • How are dynamic arrays allocated? deallocated? • How can a pointer be passed by value/by reference to a function? • What are dynamically allocated objects? Objects containing dynamically allocated members? What may be potential problems with the latter? • What are the big three operations? • What is a destructor? Why is it needed? When is it executed? How is it declared/defined? • What is a copy-constructor? Why is it needed? When is it executed? How is it declared/defined? • What is operation overloading? What is overloaded assignment? Why is it needed for objects with dynamic members? How is it declared/defined? • What is this-pointer? What is protection against self-assignment? How is this-pointer used for that? • What is stackability of an operation? How can an overloaded assignment be made stackable?