C++ Grammar Knowledge
This post talks about the knowledge (grammar, concepts) of C++.
Data Types
Basic Data Types
There are several data type in C++ and each data type could be regarded as an “object”. The object has an area of memory and the address of the memory. The memory stores value of the data and its address could be get by adding a &
in the left.
e.g. int a = 3;
and &a
is its address.
Pointer
There is also a kind of data type names pointer, which also has an area of memory and the address of the memory. Differently from the normal data type, the memory stores an address of another object. By adding a &
could get the address of the pointer, and adding a *
could get the object that the pointer pointing to.
e.g. int a = 3; int* b = &a;
and &b
is the address of pointer b
, and b
is the address of a
, which is &a
, and *b
is the value in address &a
, which is a = 3
.
Reference
Reference is a special data type and it is another name of the object. The object could be normal data type of pointer. A reference shares the same address of the object itself.
e.g. int a = 3; int& b = a;
. by changing the value of b
will change the value of a
and vice versa. &b
is same as &a
.
e.g. int a = 3; int* b = &a; int*& c = b;
. *b
is a
, *c
is a
. &c
is the same with &b
, c
is the same with &a
.
The reference is mainly used when passing parameters to a function. It could saves time and space.
Function Parameter Passing and Return Modes
When passing parameters to functions, the passing has following two modes.
Passing by value | Passing by reference |
---|---|
void function (typename a) {} |
void function (typename& a) {} |
Typename could be two main categories Normal type: int , bool , float , double , class , etcPointer: int* , bool* , float* , double* , int[] , class* , etc |
Same with left |
Copy the content of outer argument into parameter a . The parameter a only valid inside the function. |
Create another name of outer argument. The parameter a shares the same address of outer parameter. The parameter a only valid inside the function |
Deep copy of outer argument, cost time and space if the typename is normal type with large memory. e.g. vector<int> , class |
NO copy of outer argument, save time and space |
All modification to a itself won’t reflect outside the function.If the typename is a pointer, the content copied is the address of another object. Using *a could also operate the object that outer argument points to. So the modification to the object a points to could reflect outside the function |
Any modification to a is the modification to outer argument. If the passing parameters shouldn’t be changed. Use void function (const typename& a) {} |
When returning results from a function, we could announce the type of return type like int func()
or int& func()
. Inside the function, the return xx;
Return by value | Return by reference |
---|---|
int function() { return xx; } |
int& function() { static int a = 0; return a; } |
Caller will create a copy same as the returned object, cost lots of resource | Caller will have direct access to the original object, save lots of resource |
Suitable for built-in types or small structs | Suitable for large structs or classes |
Can return the local variables inside the function. Can also return unique_ptr / shared_ptr pointing to a new created class |
Can only return static variable, or class fields |
Return result is a rvalue (only can be placed on the right of operator = ) |
Return result is a lvalue (can be placed on the left of operator = ) |
Common usages of return by reference
- Return a static variable
- Return input reference
- Return
*this
- Return some protected/private fields inside the class
See the Pointer and Smart Pointer section for more info.
const
for Pointer
When const
is used to describe a variable, that means the value of the variable cannot be changed. const
could also be used to describe the pointer. (左定值,右定向)
1 | int a = 8; |
When the const is used to describe the member method of a class in the end, it means this method cannot change the variable inside the class. This method is a read-only method.
Pointer and Smart Pointer
Pointer type | Description |
---|---|
raw pointer (*) | Stores an address of the object, but not own the object, which means the object resource could be destroyed by others. |
unique_ptr | Smart pointer. Hold a pointer pointing to a memory and this memory cannot be pointed by other smart pointers. Destroying this unique_ptr will destroy the memory resource automatically. In other words, this unique_ptr owns the memory. Needs to use std::move() to transfer the ownership. |
shared_ptr | Smart pointer. A memory resource could be pointed to by several shared_ptr. Share_ptr counts how many share_ptr pointing to this memory. The memory resource will be destroyed once the all the shared_ptr are destroyed. |
weak_ptr | Points to a memory together with other shared_ptr, but weak_ptr doesn’t increase the count of how many shared_ptr points to the memory. Thus weak_ptr needs to check whether the object is still alive |
Smart pointer means the object which is pointed to will be automatically deallocate when the object can no longer be referenced. In other words, the object resource will be destroyed when the pointer is destroyed.
Passing a shared_ptr
to a function by value will increase the count the shared_ptr
. Since the parameter only exist in the function. Once the function ends, the count decreases.
1 | // unique_ptr |
Shared Pointer implementation
1 |
|
Lock of Thread
When thread A and thread B needs to operate data in thread C. There will be problem since the data from thread C vary in random time. Therefore, a lock needs to be applied to the data in thread C. The lock could guarantees the data in thread C only be modified by one thread.
1 | // In thread C |
When a thread is a loop and it needs to hangout during the normal time and could be trigger by other thread. The std::condition_variable
could be used together with std::unique_lock
and std::mutex
1 | std::mutex data_mutex |
Operators Override
1 | class A{ |
a = b
equals to a.operator=(b)
Virtual Functions & Polymorphism
Principles: Virtual Tables and Virtual Table Pointer
virtual
keyword marks the function can be overrided or is overriding previous functions in base class. See more in here.
The deconstrucor function of base class should be marked as virtual
.
override
keyword is to make sure the override behaviour happens correctly. The compiler will throw warnings if the function in derivated class doesn’t happen the override behaviour towards functions in base class.
Memory Management
Memory categories (From high address to low address)
- Stack
- Heap
- Static and const values (non-initialized)
- Static and const values (initialized)
- Code Segment
Object Storage
- Static storage duration objects
- Created before entering main
- Static initialization
- Dynamo initialization
- Thread storage duration objects
- Created before thread started, similar to static storage duration objects
- Automatic storage duration objects
- For variables inside function
- Allocation on the stack
- Dynamic storage duration objects
- With a call to
new/delete
, ormalloc/free
- Return the address to the allocated memory from Head
- Smart pointer
- With a call to
Common problems
- Cannot create a space in heap
- Forget to initialize the content in heap
- Forget to free the heap space
1 | // allocate n bytes |
Hash functions
1 | // Define a hash function for std::vector<double> |
Grammar and common std types
- initialization
- length
- traversal
- functions
1 | // =================================================== |
String implementation
1 |
|