design patterns
play

Design Patterns Mark Redekopp 2 Plugging the leaks SMART POINTERS - PowerPoint PPT Presentation

1 CSCI 104 C++11 Features Design Patterns Mark Redekopp 2 Plugging the leaks SMART POINTERS 3 C++11, 14, 17 Most of what we have taught you in this class are language features that were part of C++ since the C++98 standard New,


  1. 1 CSCI 104 C++11 Features Design Patterns Mark Redekopp

  2. 2 Plugging the leaks SMART POINTERS

  3. 3 C++11, 14, 17 • Most of what we have taught you in this class are language features that were part of C++ since the C++98 standard • New, helpful features have been added in C++11, 14, and now 17 standards – Beware: compilers are often a bit slow to implement the standards so check the documentation and compiler version – You often must turn on special compile flags to tell the compiler to look for C++11 features, etc. • For g++ you would need to add: -std=c++11 or -std=c++0x • Many of the features in the these revisions to C++ are originally part of 3 rd party libraries such as the Boost library

  4. 4 Pointers or Objects? Both! • In C++, the dereference class Thing operator (*) should appear { before… }; – A pointer to an object int main() – An actual object { Thing t1; • "Good" answer is Thing *ptr = &t1 – A Pointer to an object // Which is legal? • "Technically correct" answer… *t1; *ptr; – EITHER!!!! } • Due to operator overloading we can make an object behave as a pointer – Overload operator *, &, ->, ++, etc.

  5. 5 A "Dumb" Pointer Class • We can make a class template <typename T> class dumb_ptr operate like a pointer { private: T* p_; public: • Use template parameter as dumb_ptr(T* p) : p_(p) { } T& operator*() { return *p_; } the type of data the T* operator->() { return p_; } dumb_ptr& operator++() // pre-inc pointer will point to { ++p_; return *this; } }; • Keep an actual pointer as int main() private data { int data[10]; • Overload operators dumb_ptr<int> ptr(data); for(int i=0; i < 10; i++){ • This particular class doesn't cout << *ptr; ++ptr; } really do anything useful } – It just does what a normal pointer would do

  6. 6 A "Useful" Pointer Class • I can add automatic template <typename T> class unique_ptr { private: memory deallocation T* p_; public: so that when my local unique_ptr(T* p) : p_(p) { } ~unique_ptr() { delete p_; } "unique_ptr" goes T& operator*() { return *p_; } T* operator->() { return p_; } unique_ptr& operator++() // pre-inc out of scope, it will { ++p_; return *this; } }; automatically delete int main() what it is pointing at { unique_ptr<Obj> ptr(new Obj); // ... ptr->all_words() // Do I need to delete Obj? }

  7. 7 A "Useful" Pointer Class • What happens when template <typename T> class unique_ptr { private: I make a copy? T* p_; public: • Can we make it unique_ptr(T* p) : p_(p) { } ~unique_ptr() { delete p_; } T& operator*() { return *p_; } impossible for T* operator->() { return p_; } unique_ptr& operator++() // pre-inc anyone to make a { ++p_; return *this; } }; copy of an object? int main() { – Remember C++ unique_ptr<Obj> ptr(new Obj); unique_ptr<Obj> ptr2 = ptr; provides a default // ... ptr2->all_words(); "shallow" copy // Does anything bad happen here? } constructor and assignment operator

  8. 8 Hiding Functions • Can we make it impossible for template <typename T> class unique_ptr anyone to make a copy of an { private: object? T* p_; public: – Remember C++ provides a default unique_ptr(T* p) : p_(p) { } "shallow" copy constructor and ~unique_ptr() { delete p_; } assignment operator T& operator*() { return *p_; } T* operator->() { return p_; } • Yes!! unique_ptr& operator++() // pre-inc – Put the copy constructor and { ++p_; return *this; } private: operator= declaration in the unique_ptr(const UsefultPtr& n); private section…now the unique_ptr& operator=(const UsefultPtr& n); implementations that the compiler }; provides will be private (not accessible) int main() • { You can use this technique to hide unique_ptr<Obj> ptr(new Obj); "default constructors" or other unique_ptr<Obj> ptr2 = ptr; // Try to compile this? functions }

  9. 9 A "shared" Pointer Class • Could we write a pointer class where template <typename T> we can make copies that somehow class shared_ptr { public: "know" to only delete the underlying shared_ptr(T* p); object when the last copy of the smart ~shared_ptr(); T& operator*(); pointer dies? shared_ptr& operator++(); • Basic idea } shared_ptr<Obj> f1() – shared_ptr class will keep a count of { how many copies are alive shared_ptr<Obj> ptr(new Obj); cout << "In F1\n" << *ptr << endl; – shared_ptr destructor simply return ptr; decrements this count } • If count is 0, delete the object int main() { shared_ptr<Obj> p2 = f1(); cout << "Back in main\n" << *p2; cout << endl; return 0; }

  10. 10 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – Constructors/copies increment this doit(p1); return 0; count } – shared_ptr destructor simply void doit(shared_ptr<Obj> p2) decrements this count { • If count is 0, delete the object if(...){ shared_ptr<Obj> p3 = p2; shared_ptr p1 ControlObjPtr } } ControlObj RefCnt: 1 Actual Pointer Object

  11. 11 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – shared_ptr destructor simply doit(p1); return 0; decrements this count } • If count is 0, delete the object void doit(shared_ptr<Obj> p2) { if(...){ shared_ptr<Obj> p3 = p2; shared_ptr p1 ControlObjPtr } } ControlObj RefCnt: 2 shared_ptr p2 Actual Pointer Object ControlObjPtr

  12. 12 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – shared_ptr destructor simply doit(p1); return 0; decrements this count } • If count is 0, delete the object void doit(shared_ptr<Obj> p2) { if(...){ shared_ptr<Obj> p3 = p2; shared_ptr p1 ControlObjPtr } } ControlObj RefCnt: 3 shared_ptr p2 Actual Pointer Object ControlObjPtr shared_ptr p3 ControlObjPtr

  13. 13 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – shared_ptr destructor simply doit(p1); return 0; decrements this count } • If count is 0, delete the object void doit(shared_ptr<Obj> p2) { if(...){ shared_ptr<Obj> p3 = p2; shared_ptr p1 ControlObjPtr } // p3 dies } ControlObj RefCnt: 2 shared_ptr p2 Actual Pointer Object ControlObjPtr

  14. 14 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – shared_ptr destructor simply doit(p1); return 0; decrements this count } • If count is 0, delete the object void doit(shared_ptr<Obj> p2) { if(...){ shared_ptr<Obj> p3 = p2; shared_ptr p1 ControlObjPtr } // p3 dies } // p2 dies ControlObj RefCnt: 1 Actual Pointer Object

  15. 15 A "shared" Pointer Class • Basic idea – shared_ptr class will keep a count of int main() { how many copies are alive shared_ptr<Obj> p1(new Obj); – shared_ptr destructor simply doit(p1); return 0; decrements this count } // p1 dies • If count is 0, delete the object void doit(shared_ptr<Obj> p2) { if(...){ shared_ptr<Obj> p3 = p2; } // p3 dies } // p2 dies ControlObj RefCnt: 0 Actual Pointer Object

  16. 16 C++ shared_ptr • #include <memory> C++ std::shared_ptr / #include "obj.h" boost::shared_ptr using namespace std; – Boost is a best-in-class C++ library of shared_ptr<Obj> f1() code you can download and use with { all kinds of useful classes shared_ptr<Obj> ptr(new Obj); // ... • Can only be used to point at dynamically cout << "In F1\n" << *ptr << endl; allocated data (since it is going to call return ptr; delete on the pointer when the reference } count reaches 0) int main() • Compile in g++ using '-std=c++11' since { shared_ptr<Obj> p2 = f1(); this class is part of the new standard cout << "Back in main\n" << *p2; library version cout << endl; return 0; } $ g++ -std=c++11 shared_ptr1.cpp obj.cpp

  17. 17 C++ shared_ptr • #include <memory> Using shared_ptr's you can put #include <vector> pointers into container objects #include "obj.h" using namespace std; (vectors, maps, etc) and not have to worry about iterating through int main() { and deleting them vector<shared_ptr<Obj> > myvec; • When myvec goes out of scope, it shared_ptr<Obj> p1(new Obj); deallocates what it is storing myvec.push_back( p1 ); (shared_ptr's), but that causes the shared_ptr<Obj> p2(new Obj); shared_ptr destructor to myvec.push_back( p2 ); automatically delete the Objs return 0; // myvec goes out of scope... • Think about your project } homeworks …this might be (have been) nice $ g++ -std=c++11 shared_ptr1.cpp obj.cpp

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend