Project C++: Smart Pointers Takeaway submitted. Next submission: Nim Oct 26 th Remember: okay to change framework Make sure all games work with framework Memory checks Your program should do proper memory management! Questions Announcement Final exam Tuesday, November 18 th 12:30pm 2:30pm Rm 70-3690 The Plan Today: STL 1 Wednesday: STL 2 Thursday: Smart Pointers Memory Leak A bug in a program that prevents it from freeing up memory that it no longer needs. As a result, the program grabs more and more memory until it finally crashes because there is no more memory left. In short: Allocating without cleaning up. Pointer Ownership Everything that is a pointer should be owned Responsible for cleanup when finished Should be known to programmer Should be by design during implementation. Owner and only owner should perform a delete.
Dangling Pointers Pointer is pointing to something that it shouldn t be. Can happen if: If the scope of a pointer extends beyond that of the object being pointed to i.e Returning a pointer to a local variable. If a dynamically allocated memory cell is freed explicitly and then the pointer pointing to such a space is used in subsequent code. Getting around these problems The smart pointer Prevents memory leaks and dangling pointers Wrapper class that owns a pointer to an object Smart pointer ptr The Smart Pointer The Smart Pointer The smart pointer should look and act like a regular pointer: Should support -> Should support * Should be smarter than your average pointer. Reduce memory leaks Reduce dangling pointers Take ownership STL has a standard smart pointer that is a wrapper around a regular pointer class T* ptr; public: explicit (T* p = 0) : ptr(p) ~() delete ptr; T& operator*() return *ptr; T* operator->() return ptr; //... ; What makes smart is that it takes ownership of the pointer and cleans up class T* ptr; public: explicit (T* p = 0) : ptr(p) ~() delete ptr; T& operator*() return *ptr; T* operator->() return ptr; //... ;
Using Instead of void foo() MyClass* p(new MyClass); p->dosomething(); delete p; Use void foo() <MyClass> p(new MyClass); p->dosomething(); p will cleanup after itself Automatic cleanup Reduces memory leaks Automatic initialization Includes a default constructor that sets pointer to NULL Avoid dangling pointers Dangling pointers MyClass* p(new MyClass); MyClass* q = p; delete p; p->dosomething(); // Watch out! p is now dangling! p = NULL; // p is no longer dangling q->dosomething(); // Ouch! q is still dangling! Dangling pointers can be avoided by redefining assignment <T>& <T>::operator=(<T>& rhs) if (this!= &rhs) delete ptr; ptr = rhs.ptr; rhs.ptr = NULL; return *this; Other things that can be done during assignment p = q Create a new copy Ownership transfer use this mechanism Reference Counting Pointed object maintains count Reference Linking Smart pointer maintains count Copy on write Reference Counts Maintaining the Reference Count The reference count will change when: Smart pointer is constructed Smart pointer is copy constructed Smart pointer is assigned to a new SmartPointer. SmartPointer s destructor is called..
The Smart Pointer Maintaining the Reference Count Meaning the smart pointer must define Constructor Copy constructor operator= Destructor For efficiency s sake (this IS C++), all containers will store their objects by value. Note: the smart pointer is a friend to the class of pointers that it is managing. Questions? Funny thing about C++ Inheritance You can only gain polymorphic behavior on pointers (or references) to objects an not on objects themselves. Vehicle V = Car (); // not allowed Vehicle *V = new Car (); // okay class Base /*...*/ ; class Derived : public Base /*...*/ ; Base b; Derived d; vector<base> v; v.push_back(b); // OK v.push_back(d); // error vector<base*> v; v.push_back(new Base); // OK v.push_back(new Derived); // OK too // cleanup: you must do explicitly! for (vector<base*>::iterator i = v.begin(); i!= v.end(); ++i) delete *i; Using smart pointers: vector< linked_ptr<base> > v; v.push_back(new Base); // OK v.push_back(new Derived); // OK too // cleanup is automatic
Another problem with maintaining maps of pointers to objects. These STL classes will compare the items placed in them Meaning that actual pointer values (memory addresses) will be compared What we would like instead is to compare the objects being pointed to. Smart pointers can be extended to provide this. How? By redefining operator< Warning: STL containers may copy and delete their elements behind the scenes all copies of an element must be equivalent Should only use reference counting smart pointers with STL containers Questions? Smart Pointers How can I get them The only Standard smart pointer (STL) is the Copies are not equivalent Uses ownership method on copy Other smart pointers (reference counting) are available from Web page previously referenced. Summary Smart Pointers Wrapper class on a pointer Standard smart pointer: Takes ownership of pointer Reduce memory leaks Reduce dangling pointer Comparison operator for use in STL classes. Use with caution Questions? Have a nice weekend.