Informatik II June 28, 2010 Summary Philipe Fatio Contents 1 2 Language . . . . . . . . . . . . . 1.1 Expressions . . . . . . . 1.2 Declarations . . . . . . . 1.3 Built-in Types . . . . . . 1.4 Modifiers . . . . . . . . 1.5 Standard Library Types . 1.6 Classes . . . . . . . . . . 1.7 Other Types . . . . . . . Numerics . . . . . . . . . . . . . 2.1 Time Integration . . . . . 2.2 Algorithmic Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 1 1 2 3 5 6 6 6 Informatik II – Summary 1 Language 1.1 Expressions Expressions that don’t require creating a new object, such as a=b, ++a, p[i], p->m, x.m, a?b:c, a,b etc. are lvalues, meaning they may appear on the left side of an assignment. Other expressions and conversions create temporary objects to hold the result, which are const. An expression used as a statement discards the final result. Philipe Fatio – June 28, 2010 1.3 Built-in Types All built-in types are numeric. They are not automatically initialized to 0 unless global or static. 1 int a, b=0; 2 static double x; // 0.0 int a, b, c; 2 a+b; // Legal, add a and b, discard the sum 3 a=b=c; // Legal, assign c to b, then new b to a 1 int(-3.8); // -3 4 (a+=b)+=c; // Legal, add b to a, then add c to a 2 -7/4; // -1 5 a+b=c; // Error, a+b is const 6 double(a)=b; // Error, double(a) is const A declaration creates a type, object, or function and gives it a name. The syntax is a type name followed by a list of objects with possible modifiers and initializers applying to each object. A name consists of upper or lowercase letters, digits, and underscores with a leading letter. (Leading underscores are allowed but may be reserved). An initializer appends the form =x where x is an expression, or (x,y) for a list of one or more expressions. For instance, 1 2 5 const double& pi=PI; modified // OK Pointers A pointer stores the address of another object, and unlike a reference, may be moved to point elsewhere. The expression &x means address of x and has type pointer to x. If x has type T, then &x has type T*. If p has type T*, then *p is the object to which it points, which has type T. The * and & operators are inverses, e.g. *&x == x. Two pointers are equal if they point to the same object. All pointer types are distinct, and can only be assigned pointers of the same type or 0 (NULL). There are no run time checks against reading or writing the contents of a pointer to invalid memory. This usually causes a segmentation fault or general protection fault. *p=5; // i=5 p=new int(6); // OK, p points to int with value 6 4 p=new char(’a’); // Error, even though char 5 p=6; // Error, no conversion from int to pointer int *p, q; // p is a pointer, q is an int 6 p=0; // OK const int a=0, b=0; // a and b are both const 7 p=i-5; // Error, compiler can’t know this is 0 8 *p=7; // Segmentation fault: writing to address 0 9 int *q; *q; // Segmentation fault: q is not initialized in the declaration. By convention, const objects are UPPERCASE when used globally or as parameters. const double PI=3.14159265359; // Assignment to PI not allowed declares s1 to be a string with initial value ””, s2, s3, and s4 to be strings with initial value ”xxx”, p to be a pointer to string, a to be an array of 5 strings (a[0] to a[4] with initial values ””), and next_Word to be a function that takes no parameters and returns a string. double& pi=PI; // Error, would allow PI to be 3 const objects cannot be modified once created. They must be 1 // i=4; 4 int i=3, *p=&i; // p points to i, *p == 3 string s1, s2=”xxx”, s3(”xxx”), s4(3,’x’), *p, a[5], next_Word(); // r is an alias for i r=4; 2 In a declaration, modifiers before the type name apply to all objects in the list. Otherwise they apply to single objects. 1 int& r=i; 3 1 1.4 Modifiers 1.2 Declarations int i=3; 2 // a’s value is undefined Conversion from a floating point type to an integer type drops the decimal part and rounds toward 0. int divisions round toward 0. 1 1 A reference creates an alias for an object that already exists. It must be initialized. A reference to a const object must also be const. –1– converts to int initialized, reading random memory Informatik II – Summary A pointer to a const object of type T must also be const, of type const T*, meaning that the pointer may be assigned to but its contents may not. Philipe Fatio – June 28, 2010 The bare name of an array is a const pointer to the first element. If p is a pointer to an array element, then p+i points i elements ahead, to p[i]. By definition, p[i] is *(p+i). Arrays do not support copying, assignment, or comparison. 1 int a[5], b[5]=a; // Error: can’t initialize b 2 b=a; // Error: can’t assign arrays 3 b==a; // false, comparing pointers, not contents 4 ”abc”==”abc”; // false, comparing pointers to 2 this way 1 const double PI=3.1415926535898; 1 int a[5]; // a[0] through a[4] 2 double* p=&PI; // Error, would allow *p=4 to 2 int* p=a+2; // *p is a[2] 3 p[1]; // a[3] 3 const double* p=&PI; // OK, can’t assign to *p ( 4 p-a; // 2 5 p>a; // true because p-a > 0 6 p-1 == a+1 // true, both are &a[1] 7 *a; // a[0] or p[-2] 8 a=p; change PI but may assign to p) 4 double* const p=&PI; // Error, may assign to *p ( but not to p) 5 const double* const p=&PI; // OK, both *p and p // Error, a is const (but not *a) are const different locations The size of an array created with new[] may be an expression. The elements cannot be initialized with a list. There is no run time check against accessing deleted elements. 1 int n, *p; 2 cin >> n; 3 p=new int[n]; // Elements p[0] to p[n-1] with 4 delete[] p; // Use delete with new or new(), 5 p[0] = 1; // May crash values initially undefined Arrays The size of an array must be specified by a constant, and may be left blank if the array is initialized from a list. Array bounds start at 0. There are no run time checks on array bounds. Multi-dimensional arrays use a separate bracket for each dimension. An array name used without brackets is a pointer to the first element. 1 int a[]={0,1,2,3,4}; // Array with elements a[0] A literal string enclosed in double quotes is an unnamed static array of const char with an implied ’\0’ as the last element. It may be used either to initialize an array of char, or in an expression as a pointer to the first char. Special chars in literals may be escaped with a backslash as before. Literal strings are concatenated without a + operator (convenient to span lines). int b[5]={6,7}; // Implied ={6,7,0,0,0}; 3 int c[5]; // Not initialized, c[0] to c[4] could have any values 4 1 char s[]=”abc”; // char s[4]={’a’,’b’,’c’,’\0’}; 2 const char* p=”a” ”b\n”; // Points to the ’a’ in the 4 element array ”ab\n\0” 3 array int i=d[1][2]; // 6 6 d[-1][7]=0; // Not checked, program may crash const char* answers[2]={”no”,”yes”}; // Array of pointers to char 4 int d[][3]={{1,2,3},{4,5,6}}; // Initialized 2-D 5 1.5 Standard Library Types Iterating over containers such as a vector<T> or a string is done using standard iterators. to a[4] 2 delete[] with new[] cout << answers[1]; // prints yes (type const char *) 5 cout << answers[1][0]; // prints y (type const char) 6 ”abc”[1]; // ’b’ –2– 1 ContType C; 2 ContType::iterator // Iterator type ContType* 3 ContType::const_iterator // Iterator type const 4 for (ContType::const_iterator it = C.begin(); it ContType* (not editable, faster) != C.end(); ++it) { std::cout << *it << endl; 5 6 } Informatik II – Summary A vector<T> is like an array of T, but supports copying, assignment, and comparison. Its size can be set and changed at run time, and it can efficiently implement a stack. It has random iterators like string, which behave like type T* (or const T* if the vector is const). If T is numeric, elements are initialized to 0. It is not possible to have an initialization list such as {1,2,3}. Philipe Fatio – June 28, 2010 implicit conversion wherever needed, such as in expressions, parameter passing, assignment, and initialization. vector 1 vector<T>() // Empty vector, elements of type T 2 vector<T>(n) // n elements, default initialized 3 vector<T>(n, x) // n elements each initialized to 4 vector<T> v2=v; // Copy v to v2 5 v2=v; // Assignment 6 v2<v // Also >, ==, !=, <=, >= if defined for T 7 v.size() // n 8 vector<T>::size_type // Type of v.size(), usually x unsigned int 9 v.empty() // true if v.size() == 0 10 v[i] // i’th element, 0 <= i < v.size() (unchecked 11 v.at(i) // v[i] with bounds check, throws ), may be assigned to out_of_range 12 v.begin(), v.end() // Iterators [b, e) 13 vector<T>::iterator // Iterator type, also const_iterator 14 v.back() // v[v.size()-1] (unchecked if empty) 15 v.push_back(x) // Increase size by 1, copy x to last element 16 1.6 Classes A class defaults to private and has two special member functions, a constructor, which is called when the object is created, and a destructor, called when destroyed. The constructor is named class::class, has no return type or value, may be overloaded and have default arguments, and is never const. It is followed by an optional initialization list listing each data member and its initial value. Initialization takes place before the constructor code is executed. Initialization might not be in the order listed. Members not listed are default-initialized by calling their constructors with default arguments. If no constructor is written, the compiler provides one which default-initializes all members. The syntax is: 1 class::class(parameter list): member(value), member(value) { /* code */ } The destructor is named class::˜class, has no return type or value, no parameters, and is never const. It is usually not needed except to return shared resources by closing files or deleting memory. After the code executes, the data members are destroyed using their respective destructors in the reverse order in which they were constructed. 1 2 3 4 class Complex { 18 v.resize(n) // Change size to n >= 0 (unchecked) Complex(double r=0, double i=0): re(r), im(i) {} ˜Complex() {} // 19 v.insert(d, x) // Insert x in front of iterator d, shift, increase size by 1 20 v.erase(d) // Remove *d, shift, decrease size by 1 21 v.erase(d, e) // Remove subsequence [d, e) 22 v.clear() // v.erase(v.begin(), v.end()) Destructor 6 7 8 (5, 0) 3 4 void assign_if(bool, Complex&, const Complex&); 5 assign_if(true, a, 6); // Implicit Complex(6) 6 assign_if(true, 6, a); // Error, non-const passed to third parameter reference to Complex(6), which is const A class or member function may be templated. The type parameter must be passed in the declaration for objects of the class. Note that <class T> is equivalent to <typename T> and is only a matter of style or convention which one to use. Often class is used in class definitions and typename elsewhere. 1 template <class T> 2 class Complex { T re, im; 3 4 public: T real() const {return re;} 5 6 T imag() const {return im;} 7 Complex(T r=0, T i=0); 8 friend Complex<T> operator - (const Complex<T>&, const Complex<T>&); public: empty) v.front() // v[0] (unchecked) Complex a = 5; // Implicit =Complex(5) or =Complex 9 v.pop_back() // Decrease size by 1 (unchecked if 17 Complex(3, 4).real(); // 3 2 double re, im; // Constructor 5 1 // Other members... }; Complex a(1,2), b(3), c=4, d; // (1,2) (3,0) (4,0) (0,0) A constructor defines a conversion function for creating temporary objects. A constructor that allows 1 argument allows –3– }; 10 11 template <class T> 12 Complex<T>::Complex(T r, T i): re(r), im(i) {} 13 14 Complex<int> a(1, 2); // Complex of int 15 Complex<double> b(1.0, 2.0); // Complex of double 16 a=a-Complex<int>(3, 4); // Complex<int>(-2, -2) 17 Complex<Complex<double> > c(b, b); // Note space, not > Informatik II – Summary Templates can have default arguments and int parameters. The argument to an int parameter must be a value known at compile time. 1 template <class T, class U=T, int n=0> class V {}; 2 V<double, string, 3> v1; 3 V<char> v2; // V<char, char, 0> Classes define default behavior for copying and assignment, which is to copy/assign each data member. This behavior can be overridden by writing a copy constructor and operator= as members, both taking arguments of the same type, passed by const reference. They are usually required in classes that have destructors. If we did not overload these, the default behavior would be to copy the data pointer, resulting in two Vectors pointing into the same array. The assignment operator normally returns itself (*this) by reference to allow expressions of the form a=b=c;, but is not required to do so. this means the address of the current object; thus any member m may also be called this->m within a member function. A type defined in a class is accessed through class::type 1 template <class T> class Vector { 2 public: Philipe Fatio – June 28, 2010 A class may have more than one base class (called multiple inheritance). If both bases are in turn derived from a third base, then we derive from this root class using virtual to avoid inheriting its members twice further on. Any indirectly derived class treats the virtual root as a direct base class in the constructor initialization list. 1 class ios {...}; // good(), binary 2 class fstreambase: public virtual ios {...}; // open(), close() 3 class istream: public virtual ios {...}; // get(), operator>>() 4 class ifstream: public fstreambase, public istream {...} // Only 1 copy of ios 1.6.2 Polymorphism typedef T* iterator; 1 String s=”Hello”; typedef const T* const_iterator; 2 Vector<char> v=s; // Discards derived part of s to 3 Vector<char>* p=&s; // p points to base part of s convert 6 Vector<int>::iterator p; // Type is int* 7 Vector<int>::const_iterator cp; // Type is const int* 1.6.1 Inheritance By default, a base class is private, making all inherited members private. class D: public B defines class D as derived from (subclass of) base class (superclass) B, meaning that D inherits all of B’s members, except the constructors, destructor, and assignment operator. A protected member is accessible to derived classes but private elsewhere. public: virtual void draw() const; 3 virtual 4 ˜Shape() {} 5 }; 6 class Circle: public Shape { 7 public: void draw() const; // Must use same parameters, 8 return type, and const 9 }; 10 Shape s; s.draw(); // Shape::draw() 11 Circle c; c.draw(); // Circle::draw() 12 Shape& r=c; r.draw(); // Circle::draw() if virtual 13 Shape* p=&c; p->draw(); // Circle::draw() if 14 p=new Circle; p->draw(); // Circle::draw() if 15 delete p; // Circle::˜Circle() if virtual virtual Polymorphism is the technique of defining a common interface for a hierarchy of classes. To support this, a derived object is allowed wherever a base object is expected. 4 } class Shape { 2 virtual 3 5 1 A derived class may redefine inherited member functions, overriding any function with the same name, parameters, return type, and const-ness (and hiding other functions with the same name, thus the overriding function should not be overloaded). The function call is resolved at compile time. This is incorrect in case of a base pointer or reference to a derived object. To allow run time resolution, the base member function should be declared virtual. Since the default destructor is not virtual, a virtual destructor should be added to the base class. If empty, no copy constructor or assignment operator is required. Constructors and = are never virtual. –4– An abstract base class defines an interface for one or more derived classes, which are allowed to instantiate objects. Abstractness can be enforced by using protected (not private) constructors or using pure virtual member functions, which must be overridden in the derived class or else that class is abstract too. A pure virtual member function is declared =0; and has no code defined. Informatik II – Summary 1 class Shape { 2 protected: 3 defines a type and a set of symbolic values for it. There is an implicit conversion to int and explicit conversion from int to enum. You can specify the int equivalents of the symbolic names, or they default to successive values beginning with 0. Enums may be anonymous, specifying the set of symbols and possibly objects without giving the type a name. enum Shape(); // Optional, but default would be public 4 Philipe Fatio – June 28, 2010 public: 5 virtual void draw() const = 0; // Pure virtual, 6 virtual no definition 7 ˜Shape() {} enum Weekday {MON,TUE=1,WED,THU,FRI}; // Type 2 enum Weekday today=WED; // Object declaration, has 3 today==2 // true, implicit int(today) 4 today=Weekday(3); // THU, conversion must be 5 enum {N=10}; // Anonymous enum, only defines N 6 int a[N]; // OK, N is known at compile time 7 enum {SAT,SUN} weekend=SAT; // Object of anonymous declaration }; 8 // Circle as before 9 Shape s; // Error, protected constructor, no Shape ::draw() 10 Circle c; // OK 11 Shape& r=c; r.draw(); // OK, Circle::draw() 12 1 Shape* p=new Circle(); // OK value 2 explicit type 1.7 Other Types is a class where the default protection is public instead of private. A struct can be initialized like an array. struct 1 struct Complex {double re, im;}; // Declare type 2 Complex a, b={1,2}, *p=&b; // Declare objects 3 a.re = p->im; // Access members POD-structs A POD-struct (Plain Old Data Structure) is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined assignment operator and no user-defined destructor. A POD-struct could be said to be the C++ equivalent of a C struct. For this reason, POD-structs are sometimes colloquially referred to as “C-style structs”. typedef defines a synonym for a type. 1 typedef char* Str; // Str is a synonym for char* 2 Str a, b[5], *c; // char* a; char* b[5]; char** c; 3 char* d=a; // OK, really the same type –5– Informatik II – Summary Philipe Fatio – June 28, 2010 2 Numerics 2.1.2 The Verlet Algorithm 2.1 Time Integration Use postitions r (t), accelerations a(t) and r (t − dt), velocities do not appear. Most particle systems can be described with ODEs as: dx =u , dt m· du =F dt Criteria to select a scheme: ( ) dt r (t + dt) = r (t) + dt · u t + 2 ( ) ( ) dt dt u t+ = u t− + dt · a(t) 2 2 ( • Consistency ) Store r (t), a(t) and u t − dt 2 . • Accuracy ) ( )] [ ( dt dt +u t− u(t) = 1/2 u t + 2 2 • Stability • Efficiency Important notions: • Preservation of time symmetries • Conservation of physical quantities such as E, m · u 2.1.1 The Leapfrog Scheme • Time centered x n +1 − x n 1 = un+ /2 δt un+1/2 − un−1/2 m· = F(xn ) δt 2.1.3 Euler Scheme • Not time centered 2.2 Algorithmic Complexity Complexity determines the spectrum of problems that can practically be solved on a given computer in a given time. The Bachmann-Landau (aka. Big O) notation is used to express this scaling. O gives the upper bound on the scaling. In general: k ∑ α k −i x n + k −i = i =0 δt2 m k ∑ bk − i F n + k − i i =0 If bk is zero the scheme is explicit, else it is implicit and solutions are found iteratively. –6–