diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..600d2d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..91534f7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Cpp-Primer"] + path = Cpp-Primer + url = https://github.com/Mooophy/Cpp-Primer.git diff --git a/Cpp-Primer b/Cpp-Primer new file mode 160000 index 0000000..1d15633 --- /dev/null +++ b/Cpp-Primer @@ -0,0 +1 @@ +Subproject commit 1d15633aac9c57f973451d16d01adedf8850627d diff --git a/part_i/ch03_4_1 b/part_i/ch03_4_1 new file mode 100755 index 0000000..020def8 Binary files /dev/null and b/part_i/ch03_4_1 differ diff --git a/part_i/ch03_4_1.cpp b/part_i/ch03_4_1.cpp new file mode 100644 index 0000000..b77d628 --- /dev/null +++ b/part_i/ch03_4_1.cpp @@ -0,0 +1,26 @@ +#include +#include +using std::string; using std::cout; using std::endl; + +int main(int argc, char const *argv[]) +{ + string s("some string"); + + // if (s.begin() != s.end()) + // { + // auto it = s.begin(); + // *it = toupper(*it); + // } + + for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it) + { + *it = toupper(*it); // capitalize the current character + } + + + cout << (s) << endl; + + return 0; +} + + diff --git a/part_i/chap04_expressions.md b/part_i/chap04_expressions.md new file mode 100644 index 0000000..e3aea3e --- /dev/null +++ b/part_i/chap04_expressions.md @@ -0,0 +1,58 @@ +# Chapter 4. Expressions + +* C++ provides set of operators + * Also define what these operators do when applied to built-type operand +* **Expression** consists of single/multi operands. When evaluated, it yields a result + +## 4.1 Fundamentals + +## 4.2 Arithmetic Operators + +## 4.3 Logical and Relational Operators + +## 4.4 Assignment Operators + +## 4.5 Increment and Decrement Operators + +## 4.6 The Member Access Operators + +* `.` & `->` operators provide member access. + * `.` get member from an object of class type + * `->` dereference then get member; `ptr->mem` is synonum for `(*ptr).mem` +* `.` has higher precedence than dereference (i.e. ->) + +```cpp +// run the size member of p, then dereference the result! +*p.size(); // error: p is a pointer and has no member named size +``` + +## 4.7 The Conditional Operator + +## 4.8 The Bitwise Operators + +## 4.9 The sizeof Operator + +* **sizeof** operator returns size (in bytes) of **an expression** or **a type name**. +* It's right associative +* Result of `sizeof` is a constant expression of type `size_t` +* Syntax of `sizeof`: + * For type name: `sizeof (type)` + * For expression: `sizeof expr` +* `sizeof` doesn't evaluate its operand + +```cpp +Sales_data data, *p; +sizeof(Sales_data); // size required to hold an object of type Sales_data +sizeof data; // size of data's type, i.e., sizeof(Sales_data) +sizeof p; // size of a pointer +sizeof *p; // size of the type to which p points, i.e., sizeof(Sales_data) +sizeof data.revenue; // size of the type of Sales_data's revenue member +sizeof Sales_data::revenue; // alternative way to get the size of revenue +``` + + +## 4.10 Comma Operator + +## 4.11 Type Conversions + +## 4.12 Operator Precedence Table \ No newline at end of file diff --git a/part_i/chap05_statements.md b/part_i/chap05_statements.md new file mode 100644 index 0000000..5becf35 --- /dev/null +++ b/part_i/chap05_statements.md @@ -0,0 +1,137 @@ +# Chapter 5. Statements + +## 5.1 Simple Statements + +## 5.2 Statement Scope + +## 5.3 Conditional Statements + +## 5.4 Iterative Statements + +### 5.4.1 The `while` Statement + +### 5.4.2 Traditional for Statement + +### 5.4.3 Range `for` Statement (C++11) + +**range for statement**: simpler `for` statement that used to iterate through elements of an container + +Syntax: + +```cpp +for (declaration : expression) + statement +``` + +* where *expression* must be a sequence +* *declaration* defines a variable. Every element in sequence must be converted into declaration + * Hence, `auto` type specifier is best + +```cpp +vector v = {0,1,2,3,4,5,6,7,8,9}; +// range variable must be a reference so we can write to the elements +for (auto &r : v) // for each element in v, as we want to change r, we declare it as reference + r *= 2; // double the value of each element in v +``` + +which equivalent to + +```cpp +for (auto beg = v.begin(), end = v.end(); beg != end; ++beg) { + auto &r = *beg; // r must be a reference so we can change the element + r *= 2; // double the value of each element in v +} +``` + +Q: Why cannot use a range `for` to add elements to a `vector` + +A: In a range `for`, the value of `end()` is cached. If add elements to sequence, the value of `end()` will be invalidated. + + + +### 5.4.4 The do while Statement + +## 5.5 Jump Statements + +### 5.5.1 The `break` Statement + +### 5.5.2 The `continue` Statement + +### 5.5.3 The `goto` Statement + +??? + +## 5.6 `try` Blocks and Exception Handling + +* **throw expressions**: the part which the detecting part uses to indicate that it encountered sth run-time error +* **try blocks**: code blocks are run, from where exception may occue + * starts with `try` and ends with multiple **catch clause** + * Exceptions thrown from code executed inside a `try` block are handled by one of `cath` clauses. +* `catch` clauses are also called **exception handler** + +### 5.6.1 A `throw` Expression + +Syntax of `throw` Expression: keyword `throw` followed by an expression. + +e.g. convert following to code snippet with `throw` + +```cpp +Sales_item item1, item2; +cin >> item1 >> item2; +// first check that item1 and item2 represent the same book +if (item1.isbn() == item2.isbn()) { + cout << item1 + item2 << endl; + return 0; // indicate success +} else { + cerr << "Data must refer to same ISBN" + << endl; + return -1; // indicate failure +} +``` + +equivalent with throw expression. Rewrite the test to throw an exception rather than returning an error indicator + +```cpp +// first check that the data are for the same item +if (item1.isbn() != item2.isbn()) + throw runtime_error("Data must refer to same ISBN"); +// if we're still here, the ISBNs are the same +cout << item1 + item2 << endl; +``` + +* Throwing an exception terminates the current function and transfers control to a handler that know how to handle this error. +* `runtime_error` is one of std library exception types, defined in `stdexcept` header. + +### 5.6.2 The `try` Block + +general form of `try` block + +```cpp +try { + program-statements +} catch (exception-declaration) { + handler-statements +} catch (exception-declaration) { + handler-statements +} // . . . +``` + +??? + +### 5.6.3 Standard Exceptions + +Exception classed defined in std library, defined in 4 headers: + +1. `exception` header: most general exception class. + 1. Only show exception occur, no additional info +2. `stdexcept` header: some general-purpose exception classes, as shown in table +3. `new` header: `bad_alloc` exception type, detailed in Chapter 12.1.2 +4. `type_info` header: `bad_cast` exception type, detailed in Chapter 19.2 + +| std exception classes in `` | Description | +| -------------------------------------- | -------------------------------- | +| `exception` | Most general kind of problem | +| `runtime_error` | Problem detected only at runtime | +| `range_error` | Run-time error: ??? | + +??? Not finished ??? \ No newline at end of file diff --git a/part_i/chap06_functions.md b/part_i/chap06_functions.md new file mode 100644 index 0000000..a62ff68 --- /dev/null +++ b/part_i/chap06_functions.md @@ -0,0 +1,58 @@ +# Chapter 6. Functions + +## 6.1 Function Basics + +## 6.2 Argument Passing + +??? + +### 6.2.1 Passing Arguments by Value + +### 6.2.2 Passing Arguments by Reference + +### 6.2.3 `const` Parameters and Arguments + +### 6.2.4 Array Parameters + +### 6.2.5 `main`: Handling Command-Line Options + +### 6.2.6 Functions with Varying Parameters + +## 6.3 Return Types and the return Statement + +## 6.4 Overloaded Functions + +## 6.5 Features for Specialized Uses +??? + +### 6.5.1 Default Arguments + +### 6.5.2 Inline and `constexpr` Functions + +### 6.5.3 Aids for Debugging + +## 6.6 Function Matching + +??? + +#### Determining the Candidate and Viable Functions + +#### Finding the Best Match, If Any + +#### Function Matching with Multiple Parameters + +### 6.6.1 Argument Type Conversions + +## 6.7 Pointers to Functions + +??? + +#### Using Function Pointers + +#### Pointers to Overloaded Functions + +#### Function Pointer Parameters + +#### Returning a Pointer to Function + +#### Use `auto` or `decltype` for Function Pointer Types \ No newline at end of file diff --git a/part_i/chap07_classes.md b/part_i/chap07_classes.md new file mode 100644 index 0000000..51c01d9 --- /dev/null +++ b/part_i/chap07_classes.md @@ -0,0 +1,7 @@ +# Chapter 7. Classes + +## 7.1 Defining Abstract Data Types + +## 7.2 Access Control and Encapsulation + +## 7.3 Additional Class Features \ No newline at end of file diff --git a/part_i/chap2_variables_and_basic_types.md b/part_i/chap2_variables_and_basic_types.md new file mode 100644 index 0000000..523976f --- /dev/null +++ b/part_i/chap2_variables_and_basic_types.md @@ -0,0 +1,498 @@ +# Chapter 2. Variables and Basic Types + +## 2.3 Compound Types + +A **Compound type** is a data type that's defined using another data type. (e.g. **reference** & **pointers**) + +* A declaration of data: **base type** followed by a list of **declarators**. +* Simple declaration: declarator are just variable name + +### 2.3.1 References + +Note: After reading the book, I use [Reference declaration from cppreference.com](https://en.cppreference.com/w/cpp/language/reference) for better explanation + +Reference declaration declares a named variable as a **reference**, that is, an alias to an already-existing object or function. + +2 kinds of reference variable declaration: + +* Lvalue reference +* Rvalue reference (check chapter 13.6.1) + +**reference** (usually means "lvalue reference") declaration syntax: `S& D;`, declares declarator D as an `lvalue reference` to type determined by S + +```cpp +int ival = 1024; +int &refVal = ival; // refVal refers to (is another name for) ival +int &refVal2; // error: a reference must be initialized +``` + +* When decleared/initizlied, the reference is bound to the initialized object +* After declaration, all operation on reference are operated on bounded obj + +```cpp +refVal = 2 // assigns 2 to the object to which refVal refers, i.e., to ival +int ii = refVal; // same as ii = ival +``` + +### 2.3.2 Pointers + +A **pointer** is a compound type "points to" another data type: + +* Like reference: pointers are used for indirect access +* Unlike reference: pointer itself is an object. Hence, it can be reassigned/copied. No need to be initialized when declared + +Pointer declaration: `S* D`, where declares declarator D as a pointer to the type determined by S; `*` needed for each pointer variable + +```cpp +int *ip1, *ip2; // both ip1 and ip2 are pointers to int +double dp, *dp2; // dp2 is a pointer to double; dp is a double +``` + +#### Taking the address of an Object + +Pointer hold address of another obj. Address are obtained using `&` + +```cpp +int ival = 42; +int *p = &ival; // p holds the address of ival; p is a pointer to ival +``` + +* Reference are not obj => they don't have address. +* Type of pointer & obj must match + +```cpp +double dval; +double *pd = &dval; // ok: initializer is the address of a double +double *pd2 = pd; // ok: initializer is a pointer to double +int *pi = pd; // error: types of pi and pd differ +pi = &dval; // error: assigning the address of a double to a pointer to int +``` + +#### Pointer Value (states) + +Pointer value can be in 4 states: + +1. Point to an obj +2. Point to the location just immediately past the end of an obj +3. Point to null; i.e. bound to none +4. Invalid; values other than preceding 3; these pointers generate error + +#### Using a Pointer to Access Obj + +**Dereference operator** (`*` operator): + +```cpp +int ival = 42; +int *p = &ival; // p holds the address of ival; p is a pointer to ival +cout << *p; // * yields the object to which p points; prints 42 +``` + +#### Null Pointers + +* **Null Pointer** points to no one. +* Developer can check whether a pointer pointing to NULL. + +Multiple values to be assigned as null: + +* `nullptr`: most directed, introduced in C++11 +* `0` +* `NULL`: a **preprocessor variable** used by older programes, defined in `cstdlib` header. Replaced by preprocessor before compilation. + +```cpp +int *p1 = nullptr; // equivalent to int *p1 = 0; +int *p2 = 0; // directly initializes p2 from the literal constant 0 +// must #include cstdlib +int *p3 = NULL; // equivalent to int *p3 = 0; +``` + +* **Advice: Initialize all Pointers**. Uninitialized pointers are common source of run-time errors. +* Difference btw reference & pointer: + * reference is not obj; must be initalized; cannot be reassigned + +#### `void*` Pointers + +`void*` is a special pointer type that can hold address of any object. Type of the object at that address is unknown: + +```cpp +double obj = 3.14, *pd = &obj; +// ok: void* can hold the address value of any data pointer type +void *pv = &obj; // obj can be an object of any type +pv = pd; // pv can hold a pointer to any type +``` + +Utility of `void*` pointer: + +* Compare it to another pointer +* Pass it to or return it from a function +* Assign it to another `void*` pointer + +Details are covered in Chapter 19.1.1 + +### 2.3.3 Understanding Compound Type Declarations + +A variable definition consists of a base type and a list of declarators. Each declarator can relate its variable to the base type differently from others. e.g. shown below + +```cpp +// i is an int; p is a pointer to int; r is a reference to int +int i = 1024, *p = &i, &r = i; +``` + +#### Defining Multiple Variables + +It's easy to be confused and think type modifier applies to all variables + +```cpp +int* p; // legal but might be misleading +``` + +```cpp +int* p1, p2; // p1 is a pointer to int; p2 is an int +``` + +#### Pointers to Pointers + +A pointer is an object in memory, so like any object it also has an address. + +* `**` for a pointer to a pointer +* `***` for a pointer to a pointer to a pointer + +```cpp +int ival = 1024; +int *pi = &ival; // pi points to an int +int **ppi = π // ppi points to a pointer to an int +``` + +Dereferencing also will be cascaded + +```cpp +cout << "The value of ival\n" + << "direct value: " << ival << "\n" + << "indirect value: " << *pi << "\n" + << "doubly indirect value: " << **ppi + << endl; +``` + +#### References to Pointers + +As a pointer is an object, we can define a reference to a pointer: + +```cpp +int i = 42; +int *p; // p is a pointer to int +int *&r = p; // r is a reference to the pointer p +r = &i; // r refers to a pointer; assigning &i to r makes p point to i +*r = 0; // dereferencing r yields i, the object to which p points; changes i to 0 +``` + +Way to understand: read `r` right to left; `*&r` means the r is a reference that refer to a pointer. + +## 2.4 CONST Qualifier + +* Defining the variable's type as **const** +* const object must be initialized when creation. + +```cpp +const int i = get_size(); // ok: initialized at run time +const int j = 42; // ok: initialized at compile time +const int k; // error: k is uninitialized const +``` + +#### Initialization** and `const` + +* `const` types has restriction in terms of operations it allows + +```cpp +int i = 42; +const int ci = i; // ok: the value in i is copied into ci +int j = ci; // ok: the value in ci is copied into j +``` + +#### By Default, `const` Objects Are Local to a File + +* Compiler will replace const objects during compilation +* Hence, compiler need to know variable's initializer during compilation (not run time) +* Hence, variable must be defined in every file that wants to use the value +* So, normally, same name with `const` in multiple files are separate. + +Q: How to share `const` across multiple files? i.e. Define the `const` in 1 file, and declare it in other files to use it? + +A: add `extern` on both definition & declaration + +```cpp +// file_1.cc defines and initializes a const that is accessible to other files +extern const int bufSize = fcn(); +// file_1.h +extern const int bufSize; // same bufSize as defined in file_1.cc +``` + +### 2.4.1 Reference to `const` + +Q: How to bind a reference to an object of a `const` type. + +A: use **reference to const**: a reference to a `const` type. As it's bound to a const, it cannot be used to change value + +Syntax of reference to const: `const int &D` + +```cpp +const int ci = 1024; +const int &r1 = ci; // ok: both reference and underlying object are const +r1 = 42; // error: r1 is a reference to const +int &r2 = ci; // error: non const reference to a const object +``` + +#### Initialization and Reference to `const` + +Exception to be noted: + +1. We can bind a **reference to const** to a **nonconst object**: When we bind a reference to an object of different type, compiler will transform the RHS to a proper data type to fit LHS (e.g. create a temporary `const int temp` that equal to float value, then reference to that temporary value) + 1. Normally don't do that + +```cpp +double dval = 3.14; +const int &ri = dval; + + +const int &ri = dval; +//equal to +const int temp = dval; +const int &ri = temp +``` + +#### A Reference to `const` May Refer to an Obj that's not `const` + +Binding a **reference to const** to an object only restrict the operation we can do on reference, not the underlying obj itself. + +```cpp +int i = 42; +int &r1 = i; // r1 bound to i +const int &r2 = i; // r2 also bound to i; but cannot be used to change i +r1 = 0; // r1 is not const; i is now 0 +r2 = 0; // error: r2 is a reference to const +``` + +### 2.4.2 Pointers and `const` + +* **Pointer to const** cannot be used to change the object. +* Only can store the address of a `const` object in a **pointer to `const` (i.e. const pointer)** + +Syntax: `const S *D = &` + +```cpp +const double pi = 3.14; // pi is const; its value may not be changed +double *ptr = π // error: ptr is a plain pointer +const double *cptr = π // ok: cptr may point to a double that is const +*cptr = 42; // error: cannot assign to *cptr +``` + +Notes: + +1. we can store a nonconst object's address in a **pointer to const** + +It's helpful to think of **pointers** & **references** to `const` as pointers or references "that think they point or refer to `const`." + +#### `const` Pointers + +A pointer can also be `const`. Syntax: `const double *const pip` + +??? + +### 2.4.3 Top-Level `const` + +* **top-level const**: pointer itself is `const` +* **low-level const**: pointer point to a `const` object + +??? + +### 2.4.4 `constexpr` and Constant Expressions + +* **Constant expression** = an expression whose value cannot change & can be evaluated at compile time. +* e.g. + * literal + * `const` object initialized from constant expression + +```cpp +const int max_files = 20; // max_files is a constant expression +const int limit = max_files + 1; // limit is a constant expression +int staff_size = 27; // staff_size is not a constant expression +const int sz = get_size(); // sz is not a constant expression +``` + +#### `constexpr` Variables (C++11) + +In large system, whether an initializer is a constant expression is hard to determine. Hence, we can ask compiler to verify whether a variable is constant expression using `constexpr` declaration. + +```cpp +constexpr int mf = 20; // 20 is a constant expression +constexpr int limit = mf + 1; // mf + 1 is a constant expression +constexpr int sz = size(); // ok only if size is a constexpr function +``` + +After C++11, It's best practice to use `constexpr` instead of `const` + +#### Literal Types + +**Literal Types** = types we can use in a `constexpr` + +Types known are literal types: + +* arithmetic +* reference +* pointer types +* `nullptr` or `0` as constant expression +* Address of an obj defined outside function (check 6.1.1) + +Not literal: + +* variable ordinarily defined inside function (check 6.1.1) + +#### Pointers and `constexpr` + +When define a pointer in a `constexpr` declaration, it applies to pointer not underlying obj + +```cpp +const int *p = nullptr; // p is a pointer to a const int +constexpr int *q = nullptr; // q is a const pointer to int +``` + +a `constexpr` pointer maynot point to a `const` type: + +```cpp +constexpr int *np = nullptr; // np is a constant pointer to int that is null +int j = 0; +constexpr int i = 42; // type of i is const int +// i and j must be defined outside any function +constexpr const int *p = &i; // p is a constant pointer to the const int i +constexpr int *p1 = &j; // p1 is a constant pointer to the int j +``` + +## 2.5 Dealing With Types + +Complicated program results to complicated types: + +1. Some types are tedious/lengthy form +2. Hard to determine the exact type we need. + +### 2.5.1 Type Aliases + +**Type Alias** = a name that's a synoym for another type. So we can simplify complicated type name. + +Two way of definition: + +1. `typedef`: traditional +2. **alias declaration**: since c++11 + +Syntax of **typedef**: + +```cpp +typedef double wages; // wages is a synonym for double +typedef wages base, *p; // base is a synonym for double, p for double* +``` + +* declarator can include type modifiers (`&` `*`) to form compound type + +Syntax for **alias declaration**: + +```cpp +using SI = Sales_item; // SI is a synonym for Sales_item +``` + +After definition of type alias, it is used as a type name and can appear wherever a type name is: + +```cpp +wages hourly, weekly; // same as double hourly, weekly; +SI item; // same as Sales_item item +``` + +#### Pointers, `const` and Type Aliases + +Mixed type modifier and type aliases together + +```cpp +typedef char *pstring; // pstring is an alis for type char* +const pstring cstr = 0; // cstr is a constant pointer to char +const pstring *ps; // ps is a pointer to a constant pointer to char +``` + +* type of `pstring` is "pointer to char" +* type of `const pstring` is a "constant pointer to char", not a pointer to `const char` + +??? + +### 2.5.2 The `auto` Type Specifier (C++11) + +* Sometimes, it's impossible to determine the type of an expression when writing it. +* `auto` type specifier from C++11 tell compiler to **deduce the type from initializer**. +* variable use `auto` must have an initializer + +```cpp +// the type of item is deduced from the type of the result of adding val1 and val2 +auto item = val1 + val2; // item initialized to the result of val1 + val2 +``` + +Multiple variable declaration using `auto`: + +```cpp +auto i = 0, *p = &i; // ok: i is int and p is a pointer to int +auto sz = 0, pi = 3.14; // error: inconsistent types for sz and pi +``` + +#### Compound Types, `const` and `auto` + +* When use reference as initializer for `auto`, compiler use underlying object's type for `auto`'s type deduction + +```cpp +int i = 0, &r = i; +auto a = r; // a is an int (r is an alias for i, which has type int) +``` + +* `auto` normally ignores top-level const, while low-level const (e.g. an initializer is a pointer to const) are kept + +```cpp +const int ci = i, &cr = ci; // ci is constant integer, cr is a reference to constant integer (low-level) +auto b = ci; // b is an int (top-level const in ci is dropped) +auto c = cr; // c is an int (cr is an alias for ci whose const is top-level) +auto d = &i; // d is an int*(& of an int object is int*) +auto e = &ci; // e is const int*(& of a const object is low-level const) +``` + +??? Concepts are confusing ??? + +### 2.5.3 The `decltype` Type Specifier + +Type specifier **decltype** returns type of its operand (i.e. compiler deduces from expression but don't use the expression to initialize variable) + +```cpp +decltype(f()) sum = x; // sum has whatever type f returns +``` + +Explain: + +* compiler doesn't call `f`, but uses the type that such a call would return as type for `sum` + +How `decltype` handles **top-level const** and **reference**: returns type of that variable, including top-level const and references: + +```cpp +const int ci = 0, &cj = ci; +decltype(ci) x = 0; // x has type const int +decltype(cj) y = x; // y has type const int& and is bound to x +decltype(cj) z; // error: z is a reference and must be initialized +``` + +#### `decltype` and References + +`decltype` is the only context in which a variable defined as a reference is not treated as synonym for the referred object + +`decltype` returns a reference type for expression that yield objects that can stand on LHS of assignment + +```cpp +// decltype of an expression can be a reference type +int i = 42, *p = &i, &r = i; +decltype(r + 0) b; // ok: addition yields an int; b is an (uninitialized) int +decltype(*p) c; // error: c is int& and must be initialized +``` + +* `decltype(r)` returns a reference type +* If we want the type of referred object, use `r` in an expression (e.g. `r+0`) +* `decltype(*p)` returns a reference, must be initialized ???? + +??? Not Finished ??? \ No newline at end of file diff --git a/part_i/chap3_strings_vectors_and_arrays.md b/part_i/chap3_strings_vectors_and_arrays.md new file mode 100644 index 0000000..fa9e190 --- /dev/null +++ b/part_i/chap3_strings_vectors_and_arrays.md @@ -0,0 +1,216 @@ +# Chapter 3. Strings, Vectors, and Arrays + +## 3.3 Library vector Type + +* **vector** = collection of objs (all have same type) +* **vector** is a **container** (it "contains" other objects). Detail of containers are in Part II +* Include correct header and `using` declaration before using `vector`: + +```cpp +#include +using std::vector; +``` + +* **vector** is a **class template** (Details are introduced in Chapter 13) + * Template are not functions or classes. But can be used to generating classes or functions. + * Process of creating classes/func from template is **instantiation** +* Specify which class to instantiate by `template_name<> obj_name` (C++11 standard) + +```cpp +vector ivec; // ivec holds objects of type int +vector Sales_vec; // holds Sales_items +vector> file; // vector whose elements are vectors +``` + +Note: + +* `vector` is template, not a type. +* Types generated from `vector` must include element type (e.g. `vector`) + + +??? + +## 3.4 Introducing Iterators + +Two ways of access containers (i.e. vector): + +1. subscripts +2. **iterators** + +All containers from library have iterators, but not all of them support subscript operator. + +* iterator provide indirect access like pointers +* iterator can be valid/invalid + +### 3.4.1 Using Iterators + +* Containers have members to return iterator: `begin` & `end` + * `begin` returns an iterator denotes the 1st element: + * `end` return an iterator positioned "one past the end" of container (i.e. it's nonexistent element "off the end") + * iterator returned by `end` often referred to **off-the-end iterator** or **end iterator** +* If container is empty: `begin` `end`'s iterator are same + +```cpp +// the compiler determines the type of b and e; see ยง 2.5.2 (p. 68) +// b denotes the first element and e denotes one past the last element in v +auto b = v.begin(), e = v.end(); // b and e have the same type +``` + +For best practice: + +* Normally, we don't (want to) know the precise type of iterator. We Hence use `auto` to let compiler decide. + +#### Iterator Operations + +| operator | Description | +| ----------------------------------- | ---------------------------------------------------------------------------------------------------------- | +| `*iter` | Returns a reference to the element denoted by iterator | +| `iter->mem` | Dereference iter and fetches the member named `mem` from the underlying element. Equivalent to (*iter).mem | +| `++iter` | Increments `iter` to refer to next element | +| `--iter` | Decrements `iter` to refer to previous element | +| `iter1 == iter2` ; `iter1 != iter2` | Compares 2 iterators, they are equal if denoting same element or they are end iterator of same container | + +* Here `*iter` return a reference is actually deference the iterator (like pointer's operation). + +Following code transfer the first char to upper letter: + +```cpp +string s("some string"); +if (s.begin() != s.end()) { // make sure s is not empty + auto it = s.begin(); // it denotes the first character in s + *it = toupper(*it); // make that character uppercase, dereference it via `*it` +} +``` + +* We dereference `it` to pass the current char to `toupper` and assign the resulting uppercase letter back to into character denoted by `it` + +#### Moving Iterators from One Element to Another + +* `++/--` in/decrement operators are used to move iterators from one element to next. +* end-iterator does not denote an element, it cannot be incremented & dereferenced. + +```c++ +// process characters in s until we run out of characters or we hit a whitespace +for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it) + *it = toupper(*it); // capitalize the current character +``` + +* This code stop at whitespace + +**Key Concept: Generic Programming** + +* C++ programmers use `!=` as habit +* Only few library types have subscript operator, all library containers have iterators that defined `==` & `!=`. Most of them does not have `<` + +#### Iterator Types + +* We generally don't need to know the precise type of an iterator (like we use `auto` for vector's `size_type` member) +* Iterators from library types have `iterator` & `const_iterator` type + +```cpp +vector::iterator it; // it can read and write vector elements +string::iterator it2; // it2 can read and write characters in a string +vector::const_iterator it3; // it3 can read but not write elements +string::const_iterator it4; // it4 can read but not write characters +``` + +Terminology confusion: Iterators and Iterator Types + +* "iterator" refers to 3 entities: + * 1. *concept* of an iterator + * 2. `iterator` *type* defined by an container + * 3. *object* +* Every container class defines a type named `iterator`; it supports actions + +#### `begin` and `end` Operation + +If object returned by `begin` & `end` are `const`, then type returned by `begin`/`end` are const + +```cpp +vector v; +const vector cv; // cv is a vector with constant integer +auto it1 = v.begin(); // it1 has type vector::iterator +auto it2 = cv.begin(); // it2 has type vector::const_iterator +``` + +As shown above, the type are varying. C++11 gave **`cbegin`** & **`cend`** functions to specify type + +```cpp +auto it3 = v.cbegin(); // it3 has type vector::const_iterator +``` + +#### Combining Dereference and Member Access + +Correct way of dereference iterator and access members: + +* **`(xx)` for `(*it)` is required**. It means apply dereference operator to `it` and to apply dot operator to the result of dereferencing `it`. + +```cpp +(*it).empty() +``` + +* Incorrect usage: + * Iterator has no members + +```cpp +(*it).empty() // dereferences it and calls the member empty on the resulting object +*it.empty() // error: attempts to fetch the member named empty from it + // but it is an iterator and has no member named empty +``` + +Simplified dereference & member access: + +* **`->` operator**; + +```cpp +// print each line in text up to the first blank line +for (auto it = text.cbegin(); it != text.cend() && !it->empty(); ++it) + cout << *it << endl; +``` + +Currently remember loops that use iterators should not add elements to the container to which the iterator refer + +### 3.4.2 Iterator Arithmetic + +Operations suppoted by vector and string Iterators + +| Operator | Description | +| -------------------------- | ------------------------------------------------------------------------ | +| `iter +/- n` | generate a iterator that many elements forward/backward within container | +| `iter += n` or `iter -= n` | Compound-assignment for iterator addition/subtraction | +| `iter1 - iter2` | yields the number | +| `>`, `>=`, `<`, `<=` | A iterator < other means it appears before | + +```cpp +// compute an iterator to the element closest to the midpoint of vi +auto mid= vi.begin() + vi.size() / 2; +``` + +```cpp +if (it < mid) + // process elements in the first half of vi +``` + +??? Skip ??? + +#### Using Iterator Arithmetic + +Binary search using iterator arithmetic + +```cpp +// text must be sorted +// beg and end will denote the range we're searching +auto beg = text.begin(), end = text.end(); +auto mid = text.begin() + (end - beg)/2; // original midpoint +// while there are still elements to look at and we haven't yet found sought +while (mid != end && *mid != sought) { + if (sought < *mid) // is the element we want in the first half? + end = mid; // if so, adjust the range to ignore the second half + else // the element we want is in the second half + beg = mid + 1; // start looking with the element just after mid + mid= beg + (end - beg)/2; // new midpoint +} +``` + +* At end of `while`, `mid` will be equal to `end` or it will denote the element for which we are looking. + diff --git a/part_i/ex3_23 b/part_i/ex3_23 new file mode 100755 index 0000000..b4c3d64 Binary files /dev/null and b/part_i/ex3_23 differ diff --git a/part_i/ex3_23.cpp b/part_i/ex3_23.cpp new file mode 100644 index 0000000..02e8538 --- /dev/null +++ b/part_i/ex3_23.cpp @@ -0,0 +1,32 @@ +#include +#include + +using std::vector; +using std::cout; using std::endl; + +int main(int argc, char const *argv[]) +{ + + vector v{0,2,5,1,3,6,9,10,4,2}; + + cout << "Original vector: "; + + for (auto it = v.cbegin(); it != v.cend(); ++it) + { + cout << *it << " "; + } + + cout << endl; + + + cout << "Modified vector: "; + for (auto it = v.begin(); it != v.end(); ++it) + { + *it = *it * 2; + cout << *it << " "; + } + + cout << endl; + + return 0; +} diff --git a/part_ii/chap8_the_io_library.md b/part_ii/chap8_the_io_library.md new file mode 100644 index 0000000..a11df8d --- /dev/null +++ b/part_ii/chap8_the_io_library.md @@ -0,0 +1,11 @@ +# Chapter 8. The IO Library + +* C++ use various types in std IO libraries to handle IO. + +List of C++ classes to handle IO: + +* `istream` (input stream) type, for input operations +* `ostream` (output stream) type, for output operations +* `cin` (an `istream` obj) reads std input +* `cout` +* `cerr` (an `ostream` obj) for program error messages, writes to std error \ No newline at end of file diff --git a/part_iii/chap13_copy_control.md b/part_iii/chap13_copy_control.md new file mode 100644 index 0000000..36725d1 --- /dev/null +++ b/part_iii/chap13_copy_control.md @@ -0,0 +1,27 @@ +# Chapter 13. Copy Control + +Advanced topic for class constructors/desctructors + +Copy Control = operations of following: + +* **Copy- & Move- constructor**: define what happens when an object is initialized from another object of the same type +* **Copy- & Move- assignment**: define what happens when we assign an object (class A) to object (class B) +* **Destructor**: define what happens when object of type A destroyed + +When Copy Controls are not cleared defined, C++ compiler automatically create them; -> undefined behavior + +## 13.1 Copy, Assign, And Destroy + +### 13.1.1 Copy Constructor + +```cpp +class Foo { +public: + Foo(); // default constructor + Foo(const Foo&); // copy constructor + // ... +}; +``` + +* copy constructor's 1st parameter is a reference to the class type +* copy constructor's other parameters have default values \ No newline at end of file diff --git a/run_gcc_docker.sh b/run_gcc_docker.sh new file mode 100644 index 0000000..9de3224 --- /dev/null +++ b/run_gcc_docker.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run --rm -it -v "$(pwd)":/usr/src gcc \ No newline at end of file