Presentation is loading. Please wait.

Presentation is loading. Please wait.

C++: MEMORY MANAGEMENT, SUMMARY ID1218 Lecture 102009-11-30 Christian Schulte Software and Computer Systems School of Information and Communication.

Similar presentations


Presentation on theme: "C++: MEMORY MANAGEMENT, SUMMARY ID1218 Lecture 102009-11-30 Christian Schulte Software and Computer Systems School of Information and Communication."— Presentation transcript:

1 C++: MEMORY MANAGEMENT, SUMMARY ID1218 Lecture 102009-11-30 Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden

2 Overview  Memory management case studies resizable arrays freelists reference counting  Summary C and C++ summary… … and questions you should be able to answer L10, 2009-11-30ID1218, Christian Schulte 2

3 Case studies Memory Management L10, 2009-11-30 3 ID1218, Christian Schulte

4 Memory Management  How to… fit C++ structure, example: resizable arrays make efficient, example: free lists  Who does what? who allocates? who is responsible for deallocation? example: reference counting L10, 2009-11-30ID1218, Christian Schulte 4

5 Resizable Arrays L10, 2009-11-30 5 ID1218, Christian Schulte

6 Resizable Arrays  Should behave like an array the number of elements can be changed provides correct construction, deletion, assignment supports array access operator [] can be passed as constant reference polymorphic with respect to element type can be mixed with "normal" arrays L10, 2009-11-30ID1218, Christian Schulte 6

7 Resizable Arrays  Members current size: unsigned int element array: *Element  First attempt for integers make polymorphic in last step L10, 2009-11-30ID1218, Christian Schulte 7

8 Resizable Arrays: Class class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int get(unsigned int i) const; void set(unsigned int i, int x); ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 8

9 Constructor class IRA { private: … public: IRA(unsigned int n=8) : _n(n), _x(new int[_n]) {} … };  Any member function defined inside class is inline  Member functions can also be defined outside L10, 2009-11-30ID1218, Christian Schulte 9

10 Inline Definition class IRA { private: … public: IRA(unsigned int n=8); … }; inline IRA::IRA(unsigned int n) : _n(n), _x(new int[_n]) {}  Any member function defined inside class is inline  Member functions can also be defined outside L10, 2009-11-30ID1218, Christian Schulte 10

11 Outline Definition  Header file: class IRA { private: … public: IRA(unsigned int n=8); … };  Implementation file IRA::IRA(unsigned int n) : _n(n), _x(new int[_n]) {} L10, 2009-11-30ID1218, Christian Schulte 11

12 Copy Constructor IRA::IRA(const IRA& ira) : _n(ira._n), _x(new int[_n]) { for (unsigned int i=0; i<_n; i++) _x[i] = ira._x[i]; }  Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 12

13 Destructor IRA::~IRA() { delete [] _x; }  Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 13

14 Assignment Operator IRA& IRA::operator=(const IRA& ira) { if (this != &ira) { delete [] _x; _n = ira._n; _x = new int[_n]; for (unsigned int i=0; i<_n; i++) _x[i] = ira._x[i]; } return *this; }  Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 14

15 Access inline int IRA::get(unsigned int i) const { return _x[i]; } inline void IRA::set(unsigned int i, int x) { _x[i]=x; }  Must go into header file L10, 2009-11-30ID1218, Christian Schulte 15

16 Access: Assert Proper Use inline int IRA::get(unsigned int i) const { assert(i < _n); return _x[i]; } inline void IRA::set(unsigned int i, int x) { … }  Checked at runtime requires #include runtime error, if violated (can be looked for in debugger) ignored, if the macro NDEBUG is defined pass –DNDEBUG from commandline L10, 2009-11-30ID1218, Christian Schulte 16

17 Resizing the Array void IRA::resize(unsigned int n) { int* x = new int[n]; unsigned int m = std::min(n,_n); for (unsigned int i=0; i<m; i++) x[i] = _x[i]; delete [] _x; _n = n; _x = x; }  std::min requires #include L10, 2009-11-30ID1218, Christian Schulte 17

18 Overloading [] : First Attempt class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int operator[](unsigned int i); ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 18

19 Overloading [] : First Attempt inline int IRA::operator[](unsigned int i) { assert(i < n); return _x[i]; }  Does not work: ira[7] = 4; must pass a reference instead  Does not work: ira[7] if ira is const IRA& must also provide const version L10, 2009-11-30ID1218, Christian Schulte 19

20 Overloading [] : Second Attempt class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int& operator[](unsigned int i); const int& operator[](unsigned int i) const; ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 20

21 Overloading [] : Second Attempt inline int& IRA::operator[](unsigned int i) { assert(i < n); return _x[i]; }  Works for: ira[7] = 4; passes a reference to position in array L10, 2009-11-30ID1218, Christian Schulte 21

22 Overloading [] : Second Attempt inline const int& IRA::operator[](unsigned int i) const { assert(i < n); return _x[i]; }  Works for ira[7] if ira is const IRA& provides const version L10, 2009-11-30ID1218, Christian Schulte 22

23 Generic Resizable Arrays template class RA { private: unsigned int _n; T* _x; public: RA(unsigned int n=8); RA(const RA & ra); RA & operator=(const RA & ra); void resize(unsigned int n); T& operator[](unsigned int i); const T& operator[](unsigned int i) const; ~RA(); }; L10, 2009-11-30ID1218, Christian Schulte 23

24 Generic Copy Constructor template RA ::RA(const RA & ra) : _n(ra._n), _x(new T[_n]) { for (unsigned int i=0; i<_n; i++) _x[i] = ra._x[i]; }  Define in header file  What is executed: default constructor? yes! copy constructor? no! assignment operator? yes! L10, 2009-11-30ID1218, Christian Schulte 24

25 Mixing With Normal Arrays RA x(42); void f(int* a); void g(int a[]); f(x); g(x);  Both calls do not work: x is of type RA  Simple solution: f(&x[0]); g(&x[0]); L10, 2009-11-30ID1218, Christian Schulte 25

26 Mixing With Normal Arrays template class RA { … public: … operator T*(void) { return _x; } };  Dangerous… RA x(42); int* y = x; x.resize(1024); y[0] = 4; L10, 2009-11-30ID1218, Christian Schulte 26

27 Freelists L10, 2009-11-30 27 ID1218, Christian Schulte

28 Efficient Lists  Common behavior create and delete list cells very often  Memory allocation and deallocation is expensive  Idea store allocated but unused list cells in a freelist allocate from freelist whenever possible deallocate to freelist L10, 2009-11-30ID1218, Christian Schulte 28

29 Integer Lists class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); };  Basic required functionality no default constructor, no …  Naïve memory policy: delete single list cell refine, if different policy needed L10, 2009-11-30ID1218, Christian Schulte 29

30 Integer Lists inline IL::IL(int h, IL* t) : _hd(h), _tl(t) {} inline int IL::hd() const { return _hd; } inline void IL::hd(int h) { _hd=h; } inline IL* IL::tl() const { return _tl; } inline void IL::tl(IL* t) { _tl=t; } L10, 2009-11-30ID1218, Christian Schulte 30

31 Overloading Memory Allocation #include class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); static void* operator new(size_t s); static void operator delete(void* p); }; L10, 2009-11-30ID1218, Christian Schulte 31

32 Overloading Memory Allocation inline void* IL::operator new(size_t s) { return malloc(s); } inline void IL::operator delete(void* p) { free(p); }  Same behavior as before L10, 2009-11-30ID1218, Christian Schulte 32

33 Freelist as Static Member #include class IL { private: int _hd; IL* _tl; static IL* _free; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); static void* operator new(size_t s); static void operator delete(void* p); static void flush(); }; L10, 2009-11-30ID1218, Christian Schulte 33

34 Implementation File: Broken IL* IL::_free = NULL; void IL::flush() { for (IL* f=_free; f!=NULL; f=f->_tl) free(f); _free = NULL; }  Freelist is initially empty  Access after free! L10, 2009-11-30ID1218, Christian Schulte 34

35 Implementation File: Better IL* IL::_free = NULL; void IL::flush() { IL* f=_free; while (f!=NULL) { IL* t = f->_tl; free(f); f = t; } _free = NULL; } L10, 2009-11-30ID1218, Christian Schulte 35

36 Allocating from the Freelist inline void* IL::operator new(size_t s) { if (_free == NULL) { return malloc(s); } else { IL* il = _free; _free = _free->_tl; return il; }  Same behavior as before L10, 2009-11-30ID1218, Christian Schulte 36

37 Deallocating to the Freelist inline void IL::operator delete(void* p) { IL* il = static_cast (p); il->_tl = _free; _free = il; } L10, 2009-11-30ID1218, Christian Schulte 37

38 Generic Freelists  Not straightforward no static members in parametric classes  Solution implement type independent freelist manager pass freelist manager as extra argument to new and delete (placement new and delete) read a book… L10, 2009-11-30ID1218, Christian Schulte 38

39 Reference Counting L10, 2009-11-30 39 ID1218, Christian Schulte

40 Sharing Arrays  Desired functionality resizable array without copies (use a lot of memory) same array  What memory management policy unshared arrays: whoever created array is responsible (directly or indirectly) to delete shared array: when is the array not any longer used? L10, 2009-11-30ID1218, Christian Schulte 40

41 Reference Counting  Separate array proper:store elements handle:implement allocation protocol provide access to array proper  Store in array proper: reference count …how many handles refer to array array creation through handle: just one when array becomes shared through additional handle: increment when handle is deleted: decrement if reference count hits zero: delete array L10, 2009-11-30ID1218, Christian Schulte 41

42 Array Object Proper class AO { public: unsigned int n; int* x; unsigned int rc; }; L10, 2009-11-30ID1218, Christian Schulte 42

43 Array Handle class AH { private: AO* _ao; public: AH(unsigned int n=8); AH(const AH& ah); AH& operator=(const AH& ah); ~AH(); int& operator[](unsigned int i); … }; L10, 2009-11-30ID1218, Christian Schulte 43

44 Array Handle Constructor AH::AH(unsigned int n) : _ao(new AO) { _ao->n = n; _ao->x = new int[n]; _ao->rc = 1; } L10, 2009-11-30ID1218, Christian Schulte 44

45 Array Handle: Object Access inline int& AH::operator[](unsigned int i) { return _ao->x[i]; } … L10, 2009-11-30ID1218, Christian Schulte 45

46 Array Handle Destructor inline AH::~AH() { _ao->rc--; if (_ao->rc == 0) { delete [] _ao->x; delete _ao; }  Only if no more handles refer to object, delete object  Different design: provide constructor and destructor for array object L10, 2009-11-30ID1218, Christian Schulte 46

47 Copy Constructor inline AH::AH(const AH& ah) : _ao(ah._ao) { _ao->rc++; }  Array object is used by one additional handle L10, 2009-11-30ID1218, Christian Schulte 47

48 Assignment Operator inline AH::operator=(const AH& ah) { if (this != &ah) { if (--_ao->rc == 0) { delete _ao->x; delete _ao; } _ao = ah._ao; _ao.rc++; } return *this; }  Unsubscribe handle from current object possibly delete object  Subscribe to new object L10, 2009-11-30ID1218, Christian Schulte 48

49 Putting the Object at its Place… class AH { private: class AO { public: unsigned int n; int* x; unsigned int rc; }; AO* _ao; public: AH(unsigned int n=8); … };  Object should never be used without controlling handle L10, 2009-11-30ID1218, Christian Schulte 49

50 Smart Pointers  Generic wrapper class overloading operators -> and *  Part of C++ standard library  Use reference counting inside L10, 2009-11-30ID1218, Christian Schulte 50

51 Problems With Reference Counting  Cost every assignment and copy is expensive all access has to go through one additional indirection  Cyclic datastructures suppose reference counted lists create cyclic list all reference counts in cycle will be at least one never deleted L10, 2009-11-30ID1218, Christian Schulte 51

52 Summary: Basics L10, 2009-11-30ID1218, Christian Schulte 52

53 L10, 2009-11-30ID1218, Christian Schulte Integer Types  Basic integer type int no guarantee on range in C++ today, often 32 bits, anytime soon 64 bits, … depends on machine (think of embedded…)  Can be augmented with short or long int never shorter than s hort int (at least 16 bits) int never longer than long int (at least 32 bits )  Can be modified with signed (default) or unsigned short signed int -32768 … 32767 short unsigned int 0 … 65535 just for example! 53

54 L10, 2009-11-30ID1218, Christian Schulte Floating Point Types  Single precision float often: 32 bits  Double precision double often: 64 bits 54

55 L10, 2009-11-30ID1218, Christian Schulte Character Type  Character type char no guarantee on size, often 8 bits (ASCII, not Unicode!) unspecified whether signed or unsigned  Character constants in single quotes 'a', '1' escape sequences: '\n' for newline, etc  Also available: wchar_t for wide characters 55

56 L10, 2009-11-30ID1218, Christian Schulte Boolean Type  Boolean type bool constants true and false  Rather late addition! watch out for int with zero as false and any other value true! 56

57 L10, 2009-11-30ID1218, Christian Schulte Constants  Variables taking an immutable value cannot be changed abbreviation for commonly used values  Use const modifier const double pi = 3.1415; assignment to pi not possible 57

58 L10, 2009-11-30ID1218, Christian Schulte Operators and Expressions  No left to right order readInt() – readInt() with input 2 and 3 can be either 1 or -1  Integer division not guaranteed to round towards zero (book uses down) 8/-5 can be either -1 or -2  Comma operator: a,b evaluates to b weird things possible! 58

59 L10, 2009-11-30ID1218, Christian Schulte Unitialized Variables  Variables not by guarantee initialized unless global or static  Always give initial value important for objects 59

60 L10, 2009-11-30ID1218, Christian Schulte Static Casts  Cast at least one into double static_cast (x)/y;  Other casts dynamic_cast casting objects, later const_cast later reinterpret_cast just do it as long size fits… C-style cast ((double) x) dangerous, combines everything, don't use! 60

61 L10, 2009-11-30ID1218, Christian Schulte Example Questions  What is the relation between sizeof(int) sizeof(short int) sizeof(long int)  Answer sizeof(short int)  sizeof(int) sizeof(int)  sizeof(long int) 61

62 Summary: Arrays and Pointers L10, 2009-11-30ID1218, Christian Schulte 62

63 L10, 2009-11-30ID1218, Christian Schulte C-style Arrays  C-style arrays int a[42]; creates an array of 42 integers access cout << a[1]; assignment a[1] = a[2]+a[3]; ranges from a[0] to a[41]  Dimension of array must be constant can be evaluated at compile time to constant (eg 2*4 ) illegal int a[n] where n is variable! 63

64 L10, 2009-11-30ID1218, Christian Schulte Arrays are Pointers  C-Style arrays are basically pointers point to beginning of array  Array access a[i] translates to *(a+i)  Common idiom: pointer arithmetic pointer +/- integer: offset to pointer pointer – pointer: distance between pointers 64

65 L10, 2009-11-30ID1218, Christian Schulte Creating Dynamic Arrays  An array of size n int* a = new int[n];  Release memory later delete [] a; never forget the [] : important for arrays of objects (calling destructor) 65

66 L10, 2009-11-30ID1218, Christian Schulte Example Questions  Is this legal? int n = 6; int a[n]; const int n = 5; int b[n*4];  Answer no yes 66

67 L10, 2009-11-30ID1218, Christian Schulte Example Questions  Value of x and y … int a[] = {4,6,8}; int b[] = {1,3,5}; int x = *(a+5-*(b+1)); *(b+a[1]-a[0]) = *a; int y = *a+*(b+(&b[2]-&b[0])); value of x : *(a+5-*(b+1)) = a[5-b[1]] = a[5-3] = a[2] = 8 assignment: b[a[1]-a[0]] = a[0], that is b[2]=a[0] value of y : a[0] + b[b+2-b] = a[0] + b[2] = 4 + 4 = 8 67

68 Summary: Functions L10, 2009-11-30ID1218, Christian Schulte 68

69 L10, 2009-11-30ID1218, Christian Schulte Functions: Issues  Overloading  Declarations  Definitions  Default parameters  Inline functions  Call-by-value and call-by-reference 69

70 L10, 2009-11-30ID1218, Christian Schulte Example Questions  Is this legal? int f(int); double f(double x) { return x+1.0; } yes, absolutely! 70

71 L10, 2009-11-30ID1218, Christian Schulte Example Questions  What is the value of z? int f(double x) { return static_cast (x)-1; } int f(int* x) { return *(x+1); } int f(int x, int y=4) { return x+y-1; } int a[] = {1,2,3}; int z = a[f(1.0)]-f(1)+f(7,5)+f(&a[1]); f(1.0) = 0 f(1) = 1+4-1 = 4 f(7,5) = 7+5-1 = 11 f(&a[1]) = *(a+2) = 3 71

72 Summary: Objects and Classes L10, 2009-11-30ID1218, Christian Schulte 72

73 L10, 2009-11-30ID1218, Christian Schulte Accessors vs Mutators  Fundamental difference change object state:mutator do not change state: accessor  Accessors need to be declared const required for passing by const reference 73

74 L10, 2009-11-30ID1218, Christian Schulte Initializer Lists  In constructor after parameter list after colon: comma separated list in order of declaration of members  Only initialize, avoid initialization with subsequent assignment 74

75 L10, 2009-11-30ID1218, Christian Schulte Copying and Assignment  Copying is controlled by copy constructor IntCell(const IntCell& c) : x(c.x) {}  Assignment is controlled by assignment operator IntCell& operator=(const IntCell& c) { if (this != &c) x=c.x; return *this; }  These are synthesized by compiler if missing required for resource management 75

76 L10, 2009-11-30ID1218, Christian Schulte Destructor ~IntCell() { delete x; }  When object is deleted by delete (for heap allocated) by going out of scope (for automatically allocated) destructor is invoked for resource management 76

77 L10, 2009-11-30ID1218, Christian Schulte Default Constructor  A constructor with no arguments (or all arguments with default values) automatically generated, if no constructors provided  Important for initialization IntCell c; invokes the default constructor 77

78 L10, 2009-11-30ID1218, Christian Schulte Example  Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; 78

79 L10, 2009-11-30ID1218, Christian Schulte Example  Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; const missing! 79

80 L10, 2009-11-30ID1218, Christian Schulte Example  Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; must be: delete [] x 80

81 L10, 2009-11-30ID1218, Christian Schulte Example  Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; test for self-assignment missing 81

82 L10, 2009-11-30ID1218, Christian Schulte Example  What is the value of z? class A { public: int x; A() : x(7) {} A(int y) : x(y+4) {} A(const A& a) : x(a.x-1) {} A& operator=(const A& a) { x = a.x+3; return *this; } }; A a(4); A b; A c(a); b = c; int z = b.x; a.x = 8, c.x = 7, b.x = 10 82

83 Summary: Fine Points for Objects L10, 2009-11-30ID1218, Christian Schulte 83

84 L10, 2009-11-30ID1218, Christian Schulte Static Members  Static member is part of class, not of instance maintain data that is shared among all instances of a class  Requires declaration and definition  Declaration use keyword static done in header  Definition use class name done in implementation 84

85 L10, 2009-11-30ID1218, Christian Schulte Namespaces  Organize multiple functions, classes, etc together namespace N {… }  Inside the namespace, as always C  Outside namespace N::C  Convenience: make available single class using N::C; namespace using namespace N;  Reference to C in global namespace ::C 85

86 Summary: Inheritance L10, 2009-11-30ID1218, Christian Schulte 86

87 L10, 2009-11-30ID1218, Christian Schulte Static versus Dynamic Dispatch  Static dispatch: use compile-time type of reference to object default behavior in C++  Dynamic dispatch: use runtime type for finding member function default behavior in Java in C++: mark member functions as virtual important case: virtual destructor 87

88 L10, 2009-11-30ID1218, Christian Schulte Defaults with Inheritance  Copy constructor invokes copy constructor on base classes invokes copy constructor on newly added data members  Assignment operator invokes assignment operator on base classes invokes assignment operator on newly added data members  Destructor invokes destructors on newly added data members invokes destructors on base classes 88

89 L10, 2009-11-30ID1218, Christian Schulte Abstract Methods and Classes  Member functions can be declared abstract in base class declare as virtual declaration followed by = 0;  Must be implemented in inheriting classes instance creation only for-non abstract classes possible 89

90 L10, 2009-11-30ID1218, Christian Schulte Type Conversions  Assume we know that p is a student, really Person* p = new Student(123,"Eva",2);  Use dynamic cast Student* s = dynamic_cast (p); performs check and cast at runtime returns NULL, if not a Student 90

91 L10, 2009-11-30ID1218, Christian Schulte Example  What is the value of z? class A { public: virtual int x() { return 1; } int y() { return -1; } }; class B : public A { public: virtual int x() { return 6; } }; class C : public B { public: int y() { return 3; } }; class D : public B { public: virtual int x() { return B::x()+8; } }; C* c = new C(); D* d = new D(); int z = c->y()+dynamic_cast (d)->x()+ dynamic_cast (c)->y(); dynamic_cast (d)->x() use dynamic dispatch and returns 6+8=14 dynamic_cast (c)->y() uses static dispatch and returns -1 91

92 Summary: C Programming L10, 2009-11-30 92 ID1218, Christian Schulte

93 L10, 2009-11-30ID1218, Christian Schulte Major Differences…  No classes use structs (see later)  No references use pointers  No overloading  No templates  No default parameters  All local variable declarations must be at beginning of function  Memory management  Libraries 93

94 L10, 2009-11-30ID1218, Christian Schulte The Struct Type  Combine data into one structure struct IntPair { int x; int y; };  Also available in C++, corresponds to class IntPair { public: int x; int y; }; 94

95 L10, 2009-11-30ID1218, Christian Schulte Preprocessor Macros  Conditional compilation  Textual substitution #define FOOVALUE 1  Macros #define max(x,y) (x>y?x:y) unsafe! unsafe! things go wrong b = max(a--,c--); 95

96 L10, 2009-11-30ID1218, Christian Schulte C-Style Memory Management  Allocate n bytes from heap void* malloc(size_t n);  Free memory block p obtained by malloc void free(void* p);  Never mix new+delete with malloc+free never use delete on malloc block and vice versa 96

97 Outlook L10, 2009-11-30 97 ID1218, Christian Schulte

98 Outlook  Discussion functional programming concurrent programming object-oriented programming imperative programming system programming  Course summary L10, 2009-11-30ID1218, Christian Schulte 98


Download ppt "C++: MEMORY MANAGEMENT, SUMMARY ID1218 Lecture 102009-11-30 Christian Schulte Software and Computer Systems School of Information and Communication."

Similar presentations


Ads by Google