Generell (template) programmering Funktionsobjekt och funktionspekare Iteratorer Algoritmer Effektiv C++ Slutliga tips Genomgång av gammal tenta Daniel Aarno bishop@kth.se 2 int compare(int i1, int i2) return i1 < i2; class IntComparator public: int operator()(int i1, int i2) return i1 < i2; ; template<typename Func> int foo(func &f) return f(7,8); int main() int val = compare(5,78); //compare normal using function IntComparator comp; val = comp(67, 63); //compare using function object foo(*compare); //pass reference to function foo(comp); //pass reference to function object 4 Allt som fungerar som x ÄR x allt som fungerar som en iterator är en iterator allt som fungerar som en funktion är en funktion allt som fungerar som en behållare är en behållare Skriv funktioner så att de fungerar på allt som uppfyller konceptet för de objekt den opererar på Definera upp nya koncept där det behövs Måste vara generella (för att få bra abstraktion) Måste vara restrektiva (för effektiv implementation) 3
ostream& operator<<(ostream& os, const vector<t> &v) string sep = ""; ofstream *ofs = dynamic_cast<ofstream*>(&os); if(ofs!= 0) os << v.size(); sep = " "; for(typename vector<t>::const_iterator it = v.begin(); it!= v.end(); ++it) os << sep << *it; sep = " "; //C sorting function qsort void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *)); //Integer comparsion int int_comp(const void* a, const void* b) return *((const int*)a) < *((const int*)b); //Typedef of a function pointer typedef int (*comparator_t)(const void *, const void *); int main() const int nmemb = 12; int v[nmemb]; return os; //Sort array v using int_comp //(note int_comp is a function POINTER) qsort(v, nmemb, sizeof(int), int_comp); 6 //Use the typedef:ed type to store a pointer to a //function comparator_t mycomp = int_comp; qsort(v, nmemb, sizeof(int), int_comp); 5 istream& ReadVec(ifstream& is, vector<t> &outvec) int nmemb; is >> nmemb; outvec.clear(); istream_iterator<t> isi(is); copy(isi, istream_iterator<t>(), back_inserter (outvec)); return is; istream& operator>>(istream& is, vector<t> &outvec) ifstream *ifs = dynamic_cast<ifstream*>(&is); if(ifs!= 0) return ReadVec(*ifs, outvec); string line; getline(is, line); outvec.clear(); istringstream iss(line); T val; while(iss >> val) outvec.push_back(val); return is; 8 7
class A public: void foo() ; int main() int v[678]; sort(v, v + 678, greater<int>()); vector<int> iv(678); transform(v, v + 678, iv.begin(), v, plus<int>()); transform(v, v + 678, iv.begin(), bind2nd(plus<int>(),10)); ostream& operator<<(ostream& os, const vector<t> &v) ofstream *ofs = dynamic_cast<ofstream*>(&os); if(ofs!= 0) os << v.size() << ' '; copy(v.begin(), v.end(), ostream_iterator<t>(os, " ")); return os; vector<a> av(56); for_each(av.begin(), av.end(), mem_fun_ref(&a::foo)); void (A::*foo_func)(void) = &A::foo; A a; (a.*foo_func)(); 10 9 25 22.5 Search time Performance test 20 17.5 C Time (s) 15 12.5 10 7.5 5 Language C++ Vector addition Primes computation 2.5 0 O0 O1 O2 O3 Os JAVA Maxflow med 1000 + 1000 noder och 20000 kanter 0 5 10 15 20 25 30 35 40 Execution time (s) 12 11
Return by value Matrix operator+(const Matrix& a, const Matrix& b) Matrix c; Matrix& operator+(const Matrix& a, const Matrix& b) Matrix c; Matrix& operator+(const Matrix& a, const Matrix& b) Matrix *c = new Matrix; Undvik temporära objekt Använd initialiseringslista Undvik return-by-value Var noggran med iteratorer Använd std funktioner, algoritmer etc Optimera där det hjäper Matrix& operator+(const Matrix& a, const Matrix& b) static Matrix c; void add(const Matrix &a, const Matrix &b, Matrix dest) 14 13 struct Student string name; string addr; ; string FindAddr(list<Student> l, string name for(list<student>::iterator i = l.begin(); i!= l.end(); i++) if(*i == name) return i->addr; return ; Finn 5 fel Template <typename T> void foo(u &a, U &b) cout << foo() << endl; Template <typename T> void bar(const U &a, const U &b) cout << bar() << endl; int main () int i = 2; char c = 'a'; foo<int>(i,c); //< will not compile because temporary //< objects may not be changed bar<int>(i,c); //< compiles OK 16 15
struct Student string name; string addr; ; struct Student string name; string addr; ; Ej const& const string& FindAddr(const list<student> &l, const string &name static const string dummy; for(list<student>::const_iterator i = l.begin(); i!= l.end(); ++i) if(i->name == name) return i->addr; return dummy; string FindAddr(list<Student> l, string name) for(list<student>::iterator i = l.begin(); i!= l.end(); i++) if(*i == name) return i->addr; return ; ++i är snabbare i->name 18 17 class Guvernor string knowledge; //... ; class Actor : public Governor string lines; //... Actor& operator=(const Actor &a) if(this!= &a) lines = a.lines; //DOH! knowledge is not copied ; //This is the fix Actor& Actor::operator=(const Actor &a) Guvernor::operator=(a); //OK if operator= is not virtual (but it should be) //*(static_cast<guvernor*>(this)) = a; class NameEq const string &m_name; public: NameEq(const std::string &nam) : m_name(nam) bool operator()(const Student& s) return s.name == m_name; ; const string& FindAddr(const list<student> &l, const string &name static const string dummy; list<student>::const_iterator it = find_if(l.begin(), l.end(), NameEq(name)); return it!= l.end()? *it : dummy; if(this!= &a) lines = a.lines; 20 19
Kan en iterator avrefereras? e.end() kan inte! Är iteratorn giltig, tex efter allokering av nytt minne, insättning eller borttagning från en container? Har ett iteratorpar giltigt intervall? Göm interna funktioner i tomt namespace Överlagra bara virtual Var noggrann med const, speciellt i bibliotekskod Skilj på ISA och HASA 21