diff --git a/pages/CSE332S/CSE332S_L3.md b/pages/CSE332S/CSE332S_L3.md index 58e3216..ab5ebd7 100644 --- a/pages/CSE332S/CSE332S_L3.md +++ b/pages/CSE332S/CSE332S_L3.md @@ -1 +1,308 @@ -# Lecture 3 \ No newline at end of file +# Lecture 3 + +## C++ basic data types + +- int, long, short, char (signed, integer arithmetic) + - char is only 1 byte for all platforms + - other types are platform dependent + - can determine the size of the type by using `sizeof()`, ` INT_MAX` +- float, double (floating point arithmetic) + - more expensive in space and time + - useful when you need to describe continuous quantities +- bool (boolean logic) + +### User-defined types + +- (unscoped or scoped) enum + - maps a sequence of integer values to named constants +- function and operators + - function is a named sequence of statements, for example `int main()` +- struct and class + - similar to abstractions in cpp, extend C struct + +### struct and class + +- struct is public by default +- class is private by default +- both can have + - member variables + - member functions + - constructors + - destructors +- common practice: + - use struct for simple data structures + - use class for more complex data structures with non-trivial functionality + +```cpp +struct My_Data{ + My_Data(int x, int y): x_(x), y_(y) {} + int x_; + int y_; +}; +``` + +```cpp +class My_Data{ + public: + My_Object(int x, int y): x_(x), y_(y) {} + ~My_Object(){} + private: + int x_; + int y_; +}; +``` + +### More about native and user-defined types + +- Pointer + - raw memory address of an object + - its type constrains what types it can point to + - can take on a value of 0 (null pointer) +- Reference + - alias for an existing object + - its type constrains what types it can refer to + - cannot take on a value of 0 (**always** refer to a valid object) +- Mutable (default) vs. const types (read right to left) + - `const int x;` is a read-only variable + - `int j` is a read-write declaration + +## Scopes + +Each variable is associated with a scope, which is a region of the program where the variable is valid + +- the entire program is a global scope +- a namespace is a scope +- member of a class is a scope +- a function is a scope +- a block is a scope + +```cpp +int g_x; // global scope +namespace my_namespace{ + int n_x; // namespace scope +} +class My_Class{ + int c_x; // class scope + int my_function(){ + int f_x; // function scope + { + int b_x; // block scope + } + return 0; + } +} +``` + +A symbol is only visible within its scope + +- helps hide unneeded details (abstraction) +- helps avoid name collisions (encapsulation) + +## Motivation for pointer and reference + +We often need to _refer_ to an object, but don't want to copy it + +There are two common ways to do this: + +- Indirectly, via a pointer + - This gives the address of the object + - Requires the code to do extra work. eg, dereferencing + - Like going to the address of the object +- Directly, via a reference + - Acts as an alias for the object + - Code interacts with reference as if it were the object itself + +## Pointer and reference syntax + +### Pointer + +A pointer is a variable that holds the address of an object + +can be untyped. eg, `void *p;` + +usually typed. eg, `int *p;` so that it can be checked by the compiler + +If typed, the type constrains what it can point to, a int pointer can only point to an int. `int *p;` + +A pointer can be null, eg, `int *p = nullptr;` + +We can change to what it points to, eg, `p = &x;` + +### Reference + +A reference is an alias for an existing object, also holds the address of the object, but is only created on compile time. + +Usually with nicer interface than pointers. + +Must be typed, and its type constrains what types it can refer to. `int &r;` + +Always refers to a valid object, so cannot be null. `int &r = nullptr;` is invalid. + +Note: **reference cannot be reassigned to refer to a different object.** + +|symbol|used in declaration|used in definition| +|---|---|---| +|unary `&`|reference, eg, `int &r;`|address-of, eg, `int &r = &x;`| +|unary `*`|pointer, eg, `int *p;`|dereference, eg, `int *p = *q;`| +|`->`|member access, eg, `p->x;`|member access via pointer, eg, `p->second;`| +|`.`|member access, eg, `p.x;`|member access via reference, eg, `p.second;`| + +## Aliasing via pointers and references + +### Aliasing via reference + +Example: + +```cpp +int main(int argc, char *argv[]){ + int i=0; + int j=1; + int &r = i; + int &s = i; + r = 8; // do not need to dereference r, just use it as an alias for i + cout << "i: " << i << ", j: " << j << ", r: " << r << ", s: " << s << endl; + // should print: i: 8, j: 1, r: 8, s: 8 + return 0; +} +``` + +### Aliasing via pointer + +Example: + +```cpp +int main(int argc, char *argv[]){ + int i=0; + int j=1; + int *p = &i; + int *q = &i; + *q = 6; // need to dereference q to access the value of j + cout << "i: " << i << ", j: " << j << ", p: " << *p << ", q: " << *q << endl; + // should print: i: 6, j: 1, p: 6, q: 6 + return 0; +} +``` + +### Reference to Pointer + +Example: + +```cpp +int main(int argc, char *argv[]){ + int j = 1; + int &r = j; // r is a **reference** to j + int *p = &r; // p is a **pointer** to the address of r, here & is the address-of operator, which returns the address of the object + int * &t = p; // t is a **reference** to pointer p, here & is the reference operator, which returns the reference of the object. + cout << "j: " << j << ", r: " << r << ", p: " << *p << ", t: " << *t << endl; + // should print: j: 1, r: 1, p: 1, t: [address of p] + return 0; +} +``` + +Notice that we cannot have a pointer to a reference. But we can have a reference to a pointer. + +### Reference to Constant + +Example: + +```cpp +int main(int argc, char *argv[]){ + const int i = 0; + int j = 1; + int &r = j; // r cannot refer to i, because i is a constant (if true, alter i through r should be valid) + const int &s=i; // s can refer to i, because s is a constant reference (we don't reassign s) + const int &t=j; // t can refer to j, because t is a constant reference (we don't reassign t) + cout << "i: " << i << ", j: " << j << ", r: " << r << ", s: " << s << ", t: " << t << endl; + // should print: i: 0, j: 1, r: 1, s: 0 + return 0; +} +``` + +Notice that we cannot have a non-constant reference to a constant object. But we can have a constant reference to a non-constant object. + +### Pointer to Constant + +Example: + +```cpp +int main(int argc, char *argv[]){ + const int i = 0; + int j = 1; + int k = 2; + + // pointer to int + int *w = &j; + + // const pointer to int + int *const x = &j; + + // pointer to const int + const int *y = &i; + + // const pointer to const int, notice that we cannot change the value of the int that z is pointing to, in this case j **via pointer z**, nor the address that z is pointing to. But we can change the value of j via pointer w or j itself. + const int *const z = &j; +} +``` + +- Read declaration from right to left, eg, `int *w = &j;` means `w` is a pointer to an `int` that is the address of `j`. +- Make promises via the `const` keyword, two options: + - `const int *p;` means `p` is a pointer to a constant `int`, so we cannot change the value of the `int` that `p` is pointing to, but we can change the address that `p` is pointing to. + - `int *const p;` means `p` is a constant pointer to an `int`, so we cannot change the address that `p` is pointing to, but we can change the value of the `int` that `p` is pointing to. +- A pointer to non-constant cannot point to a const variable. + - neither `w = &i;` nor `x = &i;` is valid. + - any of the pointer can points to `j`. + +## Pass by value, pass by reference, and type inference + +Example: + +```cpp +int main(int argc, char *argv[]){ + int h = -1; + int i = 0; + int j = 1; + int k = 2; + return func(h, i, j, &k); +} + +int func(int a, const int &b, int &c, int *d){ + ++a; // [int] pass by value, a is a copy of h, so a is not the same as h + c = b; // [int &] pass by reference, c is an alias for j, the value of c is the same as the value of b (or i), but we cannot change the value of b (or i) through c (const int &b) + *d = a; // [int *] pass by value, d is a pointer to k, so *d is the value of k, a is assigned to value of k. + ++d; // d is a pointer to k, but pass by value, so ++d doesn't change the value of k. + return 0; +} +``` + +### More type declaration keywords + +`typedef` keyword introduces a "type alias" for a type. + +```cpp +typedef Foo * Foo_ptr; // Foo_ptr is a type alias for Foo * + +// the following two variables are of the same type +Foo_ptr p1 = 0; +Foo *p2 = 0; +``` + +`auto` keyword allows the compiler to deduce the type of a variable from the initializer. + +```cpp +int x = 0; // x is of type int +float y = 1.0; // y is of type float +auto z = x + y; // z is of type float, with initialized value 1.0 +``` + +`decltype` keyword allows the compiler to deduce the type of a variable from the type of an expression. + +```cpp +int x = 0; +double y = 0.0; +float z = 0.0f; + +decltype(x) a; // a is of type int, value is not initialized +decltype(y) b; // b is of type double, value is not initialized +decltype(z) c; // c is of type float, value is not initialized +``` +