# Cpp review
## General concepts
- inline function: reduce function call overhead
- compiler & linker:
source code -----> object file -----> executable file
- C++ 11
- Auto
- Lambda
- for loop iterate
- nullptr
- override & final
- new STL: forward_list, unordered_*
### 1. Operator
| Operator | Associative |
|:------|-----------:|
| a++ | left -> right |
| ++a, +a, ~a | **right -> left** |
| *, /, % | left -> right |
| +, - | left -> right |
| <<, >> | left -> right |
| >, <, >=, <= | left -> right |
| =, +=, -= | **right -> left** |
example
```
int a = 3, 2, 1;
int arr[] = {10,20,30};
a > b > c = ? // 0
2*++a = ? // 6
++a*2 = ? // 10
*arr+1 = ? // 11
```
### lvalue vs. rvalue
ref: https://medium.com/@earth875/c-c-%E5%B8%B8%E8%A6%8B%E8%A9%A6%E9%A1%8C-961619b14f88
左值讓一段 expression 成為一個有名稱的物件;而右值只是一段 expression 的結果且隨時會蒸發不見。所以像 ++x 是左值而 x++ 卻是右值。
可以利用一個簡單的方法來 check 一段 expression 是 lvalue 或 rvalue,就是看看可不可以使用 & 運算元對該 expression 取得他的位置。
左值和右值皆可以為 non-const 和 const (用 non-const 似乎較 modifiable 來的直覺),以下為範例:
<!--
string one("cute");
const string two("fluffy");
string three() { return "kittens"; }
const string four() { return "are an essential part of a healthy diet"; }
one; // modifiable lvalue
two; // const lvalue
three(); // modifiable rvalue
four(); // const rvalue
[以下待整理] -->
Lvalue: 就是一個運算式後還保留其狀態的一個物件 就是Lvalue; 也
就是說 所有的變數(variables)包含nonmodifiable, const 的變數都是Lvalue.
這邊一個重點是 const的變數也是Lvalue
Rvalue: 就是一個運算式過後其狀態就不會被保留了,
也就是一個暫存的數值
另一種說法(非完全正確, 但是可以依此來稍做判斷)
能出現在assignment 運算子(=)的左邊的稱為Lvalue, 而只能出現在右邊的稱為Rvalue
這邊只有說出現在左邊的是Lvalue, 但沒說Lvalue不能出現在右邊, 因此Lvalue在=運算子的左右兩邊都是被允許的,
而Rvalue是不能出現在左邊的; 這邊有沒有注意到, Lvalue是可以被放到右邊的, 也就是說Lvalue也可以被當作Rvalue, 但是Rvalue就不能被當作是Lvalue
### Memory
- memory allocation
global: global variable, visible by entire program
stack: local var in a func, allocated by compiler, contiguous
heap: random order
- memory alignment
k-Byte alignment
k is the data memboer with most bytes
```
class A{
int aa;
long double bb;
char c;
}
A* a = new A();
sizeof(a) // 48
```
- memory fragmentation

### Pointer
- **Nonconstant** pointer to **constant** data
e.g. arguments passed to a func
```
int a = 10, b = 15;
const int* ptr = &a;
ptr = &b;
*ptr = 20; //error
```
- **Constant** pointer to **nonconstant** data
e.g. array
```
int a[] = {10, 20 ,30};
```
### Static
- static variable (global var)
restricted in certain file
- static variable (in function)
```
void foo(){
static int counter = 0;
counter++;
cout << "times " << counter << endl;
}
```
- static member variable
owned by all classes,
- static member function
access static member var
### extern
internal linkage & external linkage
### const
https://stackoverflow.com/questions/10716769/c-difference-between-const-positioning
### Class
- Constructor is to “construct” (initialize) a class
object, NOT to allocate the memory
- copy constructor
- declare myself (MyClass) as "friend” of other class (OtherClass)
```
class ListNode
{
friend class List;
...
};
class List
{
void push_front(const T& d) {
_head = new ListNode(d, _head);
}
ListNode* _head;
};
```
### Inheritance
https://www.cprogramming.com/tutorial/size_of_class_object.html
- Virtual function is useful ONLY with polymorphism
- Explicitly calling Base constructor
- Define “virtual” Base destructor
- destructor for derived class
### polymorphism
- Program in general, execute in specific
- virtual function + dynamic binding
- about virtual: https://medium.com/theskyisblue/c-%E4%B8%AD%E9%97%9C%E6%96%BC-virtual-%E7%9A%84%E5%85%A9%E4%B8%89%E4%BA%8B-1b4e2a2dc373
- base class & derived class
```
class Base {
public:
virtual void pureVirutal() = 0; // only define interface
virtual void virtualNonOverrided(); // interface & default imple
virtual void virtualOverrided(); // polymorphism
void nonVirtual();
};
class Derived: public Base
{
public:
virtual void pureVirutal(); // must be overrided
virtual void virtualOverrided();
void nonVirtual();
};
```
Assign base-class ptr to derived class is safe, but only base class
=: "is a"
```
int main(){
Derived d, d2;
d.virtualNonOverrided(); // base
d.virtualOverrided(); // derived
d.nonVirtual(); // derived
Base b = d2; // d2 "is a" base class object
b.virtualNonOverrided(); // base
b.virtualOverrided(); // base
b.nonVirtual(); // base
Base* b_ptr = new Derived();
b_ptr->virtualNonOverrided(); // base
b_ptr->virtualOverrided(); // derived
b_ptr->nonVirtual(); // base
}
```
<!-- | base | derived |
|:------|-----------:|
| virutal | left -> right |
| ++a, +a, ~a | **right -> left** |
| *, /, % | left -> right |
| +, - | left -> right | -->
pure virtual: interface
simple virtual: interface, implementation (default)
dynamic binding, override
non-virtual: interface, implementation
<!-- ## Data structure
### set operation
#### remove item
for vector, list
```
for (it=c.begin(); it!=c.end(); )
{
if (is need delete)
it = c.erase(it);
else
it++;
}
```
for set, map
```
for (it=c.begin(); it!=c.end(); )
{
if (is need delete)
c.erase(it++);
else
it++;
}
```
-->
- when to use virtual destructor
```
Base *b = new Derived();
// use b
delete b; // Here's the problem!
```
Since Base's destructor is not virtual and b is a Base* pointing to a Derived object, delete b has undefined behaviour
To sum up, always make base classes' destructors **virtual** when they're meant to be manipulated polymorphically.
https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors