150 likes | 252 Views
The Standard Template Library – part 2. auto_ptr<>. Regular pointers may cause memory leaks void f() { SomeClass *ptr = new SomeClass; … // exception or improperly implemented early return from f() … delete ptr; // memory leak if this statement is not reached }
E N D
auto_ptr<> • Regular pointers may cause memory leaks void f() { SomeClass *ptr = new SomeClass; … // exception or improperly implemented early return from f() … delete ptr; // memory leak if this statement is not reached } • The memory leak may be avoided • We may use exception mechanism to catch exceptions • We shoud delete all allocated memory in case of early return
auto_ptr<> • auto_ptr is an object (template) that • Acts as an inteligent pointer • Owns data assigned to it • Manages asigned data to avoid memory leaks • (defined in <memory> header) void f() { std::auto_ptr<SomeClass> ptr(SomeClass); … // exception or early return from f() – ok! … // no need to delete ptr; ~auto_ptr() does it for us }
auto_ptr<> • auto_ptr owns data assigned to it • Assignment from regular pointer not allowed // std::auto_ptr<SomeClass> ptr = new SomeClass; ERROR, but there is a reset() • There may be only one one auto_ptr that owns specific object/variable • copy constructor and assignment operator move data from source auto_ptr, so they modify their arguments – unusual behaviour • auto_ptr should not be an element of a container (why?) • auto_ptr acts as an inteligent pointer • Overloads *(ptr) and ptr-> • It is a pointer to single object, not to an array, container – ok. • Does not overload pointer arithmetic operators (++, [], etc) • Extra methods : • T* get() – returns address of the owned data (or NULL), not changing ownership • T* release() – returns address of the owned data (or NULL), releasing ownership • void reset(T * ptr=0) – assignment from regular pointer, creating ownership
auto_ptr<> • copy constructor std::auto_ptr<SomeClass> ptr1(SomeClass); std::auto_ptr<SomeClass> ptr2(ptr1); // now ptr1 is empty • assignment operator std::auto_ptr<SomeClass> ptr1(SomeClass); std::auto_ptr<SomeClass> ptr2(SomeClass); ptr2=ptr1; // *ptr2 (old one) gets destructed first, // now ptr1 is empty
auto_ptr<> • auto_ptr as argument or return value • Should be passed as variable, not as reference • This way we create sink (argument) or source (ret. val.) of data • const auto_ptr • will not allow to transfer owned data to another auto_ptr • will not allow to assign data owned by another auto_ptr • ultimately will destruct owned data • changing owned data still ok. • good for sink • const auto_ptr & • for functions operating on owned data without changing ownership • examples: util/autoptr1.cpp util/autoptr2.cpp
auto_ptr<> • auto_ptr as a member variable • may make destructor not necessary • is safe even for exceptions thrown by a constructor • as opposed to regular pointers, since if constructor fails then destructor is not executed • usually requires implementing copy constructor and assignment operator • since default ones woud remove data from object being assigned
numeric_limits<> • numeric_limits<> is a template that defines various properties of a numerical types • member variables and methods should be used to determine type properties at the compile time • numeric_limits<int>::digits // no. of bits for integer types • numeric_limits<int>::max() // easy to guess • … • it is implemented as a template that has specializations for all fundamental types
Special containers • stack (LIFO queue, implemented using deque) • queue (FIFO queue, implemented using deque) • priority_queue • bitset • hash_set, hash_multiset, hash_map, hash_multimap (implemented using hash table instead of binary tree)
stack • header <stack> • simple LIFO queue implemented using deque • may be based on any container supporting: back(), push_back(), pop_back(), • just give 2nd template argument, eg.: stack<int, vector<int> > • just redirects own methods to deque methods to obtain LIFO queue • example: cont/stack1.cpp • push() • pop() • top() // get the value of topmost element // but do not remove it from stack • size() // get the current number of elemets • empty() // is it empty • operators: ==, !=, <, >, <=, >= // == returns 1 if size and all elements are equal • no more methods or operators
queue • header <queue> • simple FIFO queue implemented using deque • may be based on any container supporting: front(), back(), push_back(), pop_front() • just give 2nd template argument, eg.: queue<int, list<int> > • just redirects own methods to deque methods to obtain FIFO queue • example: cont/queue1.cpp • push() • pop() • back() // get the value of element most recently push-ed // but do not remove it from stack • front() // get the value of element at the front of queue // but do not remove it from queue • size() // get the current number of elemets • empty() // is it empty • operators: ==, !=, <, >, <=, >= // == returns 1 if size and all elements are equal • no more methods or operators
priority_queue • header <queue> • simple priority queue implemented using vector • may be based on any container supporting: front(), push_back(), pop_front(), oper.[] • just give 2nd template argument, eg.: priority_queue<int, deque<int> > • the 3rd argument is a sort criterion (defaults to operator< ) priority_queue<int, vector<int>, greater<int> > • redirects own methods to vector methods • example: cont/pqueue1.cpp • push() • pop() • top() // get the value of element of the greatest priority // but do not remove it from queue • size() // get the current number of elemets • empty() // is it empty • no more methods or operators (no operator ==, etc.)
bitset • header <bitset> • convinient class for handling fixed size sets of bits bitset<20> flags; • performing bit stream i/o • example: cont/bitset1.cpp • also to perform integer i/o in binary format • example: cont/bitset2.cpp • no copy constructor or assignment operator
bitset • bitset constructors bitset<bits>::bitset() bitset<bits>::bitset(unsigned long val) bitset<bits>::bitset(const string &sc) // no char* initialization, couple variants of string initialization • bitset methods and operators size() // return size of bitset count() // count ones any() // 1 if at least one bit set none() // !any() test(size_t idx) // is the idx-th bit set operator==(const bitset<bits>& arg) operator!=(const bitset<bits>& arg) …
bitset • bitset methods and operators set() // set all to ones set(size_t idx, int value=1) reset() // set all to zeroes reset(size_t idx) // set idx-th to zeroes flip() // negate all bits flip(size_t idx) bitwise operators (argument size must match): ^= |= &= ^ | & ~ bitwise shift operators (size_t argument): <<= << >>= >> steram operators: << >> bool operator[] (size_t idx) const // undefined behaviour if idx out of range bitset<bits>::reference operator[] (size_t idx) // returns object of special proxy type // with reference type we may: =(bool), =(const reference &), flip(), operator~(), bool() to_ulong(), to_string()