440 likes | 603 Views
Pointers and Dynamic Memory. A pointer is the memory address of a variable. A memory address is a physical location within a system’s memory space. A pointer variable is variable used to hold a pointer. It is a special data type. Pointers and Dynamic Memory.
E N D
Pointers and Dynamic Memory A pointer is the memory address of a variable. A memory address is a physical location within a system’s memory space. A pointer variable is variable used to hold a pointer. It is a special data type.
Pointers and Dynamic Memory A pointer variable can be assigned a pointer (memory address). We can declare a pointer variable: int * myIntPtr; Type of data pointed to (int), pointer symbol (*), variable name (myIntPtr).
Pointers and Dynamic Memory We can assign a memory address (pointer) to the variable: (& is called the address-of operator) myIntPtr = &myInt; Where: int myInt was declared earlier in the program.
Pointers and Dynamic Memory We can refer to the value in the location pointer to by myIntPtr with the dereferencing operator * as follows: cout << *myIntPtr << endl; If we had previously executed the statement int myInt =42; We would see ‘42’ in the output.
Pointers and Dynamic Memory Pointers can be set with the usual assign operator. int i = 42; int * p1, *p2; p1 = &i; int i 42 int *p2 int *p1 Before
Pointers and Dynamic Memory Pointers can be set with the usual assign operator. int i = 42; int * p1, *p2; p1 = &i; //-------------- p2 = p1; int i 42 int *p2 int *p1 After
Pointers and Dynamic Memory Contents of pointer variables can be set with the assign operator. int j 17 int i 42 int i = 42; int j = 17 int * p1, *p2; p1 = &i; p2 = &j; int *p2 int *p1 Before
Pointers and Dynamic Memory Contents of pointers variables can be set with the assign operator. int j 17 int i *p1 = *p2; 17 int *p2 Value of location pointed to by p2 copied to location pointed to by p1 int *p1 After
Pointers and Dynamic Memory The real power of pointers is seen when they are used to point to dynamically allocated variables. Let’s see why.
Pointers and Dynamic Memory • Dynamic variables are used just like ordinary static variables except: • They are not declared, so they have no identifiers like static variables do. • They are created during run time, not when the program is compiled.
Pointers and Dynamic Memory Storage for these variables comes from an area of memory called the free store or the heap. The creation of new dynamic variables is called memory allocation and the memory is called dynamic memory. C++ uses the new operator create a dynamic variable.
Pointers and Dynamic Memory Here are the steps: int * myIntPtr; // create an integer pointer variable myIntPtr = new int; // create a dynamic variable // of the size integer new returns a pointer (or memory address) to the location where the data is to be stored.
Pointers and Dynamic Memory Free Store (heap) int * myIntPtr myIntPtr = new int; myIntPtr
Pointers and Dynamic Memory Use pointer variable as before Free Store (heap) 1 2 3 int * myIntPtr myIntPtr = new int; myIntPtr *myIntPtr = 123;
Pointers and Dynamic Memory We can also allocate entire arrays with the new operator. These are called dynamic arrays. This allows a program to ask for just the amount of memory space it needs at run time.
Pointers and Dynamic Memory Free Store (heap) int * myIntPtr; myIntPtr = new int[4]; 0 myIntPtr 1 3 2 5 2 3 myIntPtr[1] = 325; Notice that the pointer symbol is understood, no * is used to reference the array element.
Pointers and Dynamic Memory The new operator gets memory from the free store (heap). When you are done using a memory location, it is your responsibility to return the space to the free store. This is done with the delete operator. delete myIntPtr; // Deletes the memory pointed delete [ ] arrayPtr; // to but not the pointer variable
Pointers and Dynamic Memory Dynamic memory allocation provides a more flexible solution when memory requirements vary greatly. The memory pool for dynamic memory allocation is larger than that set aside for static memory allocation. Dynamic memory can be returned to the free store and allocated for storing other data at later points in a program. (reused)
Pointers and Arrays as Parameters int *main_ptr; main_ptr = new int; set_value(main_ptr); ----------------------------------------- void set_value(int * tempPtr) { *tempPtr = 222; } 222 main_ptr tempPtr
Pointers and Arrays as Parameters int *main_ptr; main_ptr = new int[4]; set_value(main_ptr); ----------------------------------------- void set_value(int tempPtr[]) { tempPtr[1] = 222; } 222 main_ptr tempPtr
Pointers and Arrays as Const Parameters int *main_ptr; main_ptr = new int[4]; set_value(main_ptr); ----------------------------------------- void set_value(const int tempPtr[]) { tempPtr[1] = 222; } main_ptr Not allowed
Pointers and Dynamic Memory Sometimes we may want a function to change a pointer so that it points to a different location This is accomplished by using a reference parameter that is a pointer type void change_location(int* & refPtr)
Pointers and Dynamic Memory We often use a typedef statement to simplify the cumbersome syntax. typedef int* inPtr; inPtr myIntPtr; void functionEx(inPtr & localPtr);
Pointers and Dynamic Memory Some things to be careful with when using pointers. Pointers should always point to something. When a object pointed to is no longer needed, the memory should be freed with delete and the pointer should be assigned the special value null, defined in the stddef.h header file. delete myIntPtr; // return memory to free store myIntPtr = null; // point to special “nothing” value.
Pointers and Dynamic Memory A pointer not pointing to an object is considered “unassigned”. An unassigned pointer variable must not be dereferenced. A “null” pointer value should not be dereferenced. A pointer left pointing is called a dangling pointer.
Pointers and Dynamic Memory Dangling pointers can occur when two or more pointers point to the same object and one of the pointers is used with the delete operator. Returned to free store 42 42 Delete p1; int *p2 int *p1 int *p1 int *p2 A dangling pointer
Pointers and Dynamic Memory An inaccessable memory location, also called a memory leak, results from the reassignment of a pointer without first releasing the memory it pointed to. 42 42 17 17 An inaccessable object int *p2 int *p1 int *p1 int *p2 p2 = p1;
Pointers and Dynamic Memory An inaccessable memory location can also be caused by inappropriate use of new operator. 42 42 An inaccessable object int *p1 int *p1 p1 = new int;
Pointers and Dynamic Memory Pointers also introduce potential problems with the behavior of the automatic assignment operator, the copy operation, and the comparison operation. The automatic behavior produces what is called a shallow copy. Both pointers point to the same object. What we want is a deep copy. We want a copy of the data not just the pointer.
Pointers and Dynamic Memory What we wanted. int * myIntPtr; myIntPtr = new int[4]; int * myIntPtr2; myIntPtr2 = myIntPtr; 0 0 1 1 myIntPtr 2 2 3 3 myIntPtr2 Not the default behavior of ‘=‘ Free Store (heap)
Pointers and Dynamic Memory What we got! int * myIntPtr; myIntPtr = new int[4]; int * myIntPtr2; myIntPtr2 = myIntPtr; 0 1 myIntPtr 2 3 myIntPtr2 Free Store (heap)
Pointers and Dynamic Memory To handle this and other dynamic data situations, we must add additional member functions to any class that uses dynamic data. Some additional functions would want: We must overload the assignment operator. We must provide a copy constructor. We also need to add a destructor member function.
Pointers and Dynamic Memory Let’s look at the copy constructor. The principles are the same for the assignment operator overload. A copy constructor is a special constructor called when a new instance of a class is created from an existing object of that class. DynamicClass newClass(oldClass); DynamicClass newClass = oldClass;
Pointers and Dynamic Memory Class DynamicClass { public: DynamicClass (const DynamicClass & oldClass); void operator =(const DynamicClass & oldClass); ~DynamicClass (); … };
Pointers and Dynamic Memory DynamicClass::DynamicClass (const DynamicClass& oldClass) { data = new Item[someSize]; for (int i=0; i < oldClass.currentSize; i++) { data[i] = oldClass[i]; } }
Pointers and Dynamic Memory A A 0 0 oldClass 1 B 1 B data 2 C 2 C 3 D 3 D Free Store (heap)
Pointers and Dynamic Memory Now let’s apply what we’ve learned to resizing a dynamically allocated array. When the capacity of the original array is used up, we want to allocate a new larger array and copy the data from the original array to the new larger array. After the data has been copied, we can delete the original array and return the memory to free store.
Pointers and Dynamic Memory A 0 A 0 oldClass 1 B 1 B data 2 C 2 C 3 D 3 D 4 5 6
Pointers and Dynamic Memory delete [ ] oldClass; A 0 A 0 oldClass 1 B 1 B data 2 C 2 C 3 D 3 D 4 5 Return memory 6
Pointers and Dynamic Memory Class DynamicClass { public: DynamicClass (const DynamicClass & oldClass); void operator =(const DynamicClass & oldClass); ~DynamicClass (); … };
Pointers and Dynamic Memory When we are finished using a class instance, we must free any memory pointed to by variables in the class. This is done automatically by invoking the code contained in the class destructor. Failure to do so creates memory leaks. Like the constructor, the destructor does not return any data type. It has the same name as the class name but is preceded by the ‘~’ symbol. DynamicClass::~DynamicClass() { }
Pointers and Dynamic Memory The use of pointers and dynamic variables is an important problem solving tool. It gives the class builder flexibility in managing memory. It’s use does require more care on the part of the programmer, since control is now in the hands of the programmer and not the system. However, the benefits generally outweigh the disadvantages and C++ programs make heavy use of dynamic memory.