[重修] 計算機程式-4 & 5Function I, II
相當精彩的一節, 這節介紹 何時用function 還有 解釋了為什麼 主程式裡用return 0; 是回傳0給OS.
10) Function templates
重載的進階版, 避免寫太多重載函數. 可以自己寫個 library 預定義可延展的傳入data type
問題是比較慢, 另外有的程式語言會設定 stack的 limit 造成recursive 無法算出想要的答案
https://en.wikipedia.org/wiki/Recursion_(computer_science)
整理補洞如下,
1) main 是特殊的function, default 不寫的話 type為int
int main(){
....
}
這裡兩個例子是一樣的.
main(){
....
}
2) function define type 和 default value
這個範例解釋 兩個常用的觀念, line_5 是hello 這個function的define type 設定傳入的default value為1. 也就是說 line_8寫成hello() 也是ok的.
再回到line_5, 要注意的是 宣告並沒有說 int x=1 , 在這裡 "x" 寫不寫 都沒有關係 程式都可以跑 寫了只是給人看得更容易理解.
line_12 - 15 是function 的description.
3) #include<> 和 #include ""
差別在於前者直接去standard library裡找, 後者是先在local找 user define的library
4) Call random function
#include<cstdlib> <=== include srand() and rand()
可以用srand(seed) 設定種子值, 所以每次產生的亂數會不一樣
5) Storage class and Scope
- 變數可以在程式裡 活多久叫 Storage class (簡單分有 auto 跟 static)
- 變數可以在程式哪活 叫 Scope (簡單分有 local 跟 global )
一般來說function裡的變數, 一旦function 結束了就free memory了 這就叫auto. register 就是把變數放到讀寫更快的 memory方便存取.
如果宣告為static 出了function 還是會hold住 memory的值 直到程式結束.
* static default set value as 0 but not auto
6) 呼叫global
cout << ::x
這裡的 "::" 就是叫global valuable的意思
7) inline function
一般的function 就是用Stack 的方式在 Calling and called 之間互換. 其實對OS來說是種負擔 (執行速度變慢)
對小的, 不複雜的function 其實可用 inline function.
inline function 的精神就是 直接replace.
http://www.cplusplus.com/articles/2LywvCM9/
What is inline function :
The inline functions are a C++ enhancement feature to increase the execution time of a program. Functions can be instructed to compiler to make them inline so that compiler can replace those function definition wherever those are being called. Compiler replaces the definition of inline functions at compile time instead of referring function definition at runtime.
NOTE- This is just a suggestion to compiler to make the function inline, if function is big (in term of executable instruction etc) then, compiler can ignore the “inline” request and treat the function as normal function.1
The inline functions are a C++ enhancement feature to increase the execution time of a program. Functions can be instructed to compiler to make them inline so that compiler can replace those function definition wherever those are being called. Compiler replaces the definition of inline functions at compile time instead of referring function definition at runtime.
NOTE- This is just a suggestion to compiler to make the function inline, if function is big (in term of executable instruction etc) then, compiler can ignore the “inline” request and treat the function as normal function.1
Why to use –
In many places we create the functions for small work/functionality which contain simple and less number of executable instruction. Imagine their calling overhead each time they are being called by callers.
When a normal function call instruction is encountered, the program stores the memory address of the instructions immediately following the function call statement, loads the function being called into the memory, copies argument values, jumps to the memory location of the called function, executes the function codes, stores the return value of the function, and then jumps back to the address of the instruction that was saved just before executing the called function. Too much run time overhead.
The C++ inline function provides an alternative. With inline keyword, the compiler replaces the function call statement with the function code itself (process called expansion) and then compiles the entire code. Thus, with inline functions, the compiler does not have to jump to another location to execute the function, and then jump back as the code of the called function is already available to the calling program.
With below pros, cons and performance analysis, you will be able to understand the “why” for inline keyword
Pros :-
1. It speeds up your program by avoiding function calling overhead.
2. It save overhead of variables push/pop on the stack, when function calling happens.
3. It save overhead of return call from a function.
4. It increases locality of reference by utilizing instruction cache.
5. By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining)
Cons :-
1. It increases the executable size due to code expansion.
2. C++ inlining is resolved at compile time. Which means if you change the code of the inlined function, you would need to recompile all the code using it to make sure it will be updated
3. When used in a header, it makes your header file larger with information which users don’t care.
4. As mentioned above it increases the executable size, which may cause thrashing in memory. More number of page fault bringing down your program performance.
5. Sometimes not useful for example in embedded system where large executable size is not preferred at all due to memory constraints.
When to use -
Function can be made as inline as per programmer need. Some useful recommendation are mentioned below-
1. Use inline function when performance is needed.
2. Use inline function over macros.
3. Prefer to use inline keyword outside the class with the function definition to hide implementation details.
Key Points -
1. It’s just a suggestion not compulsion. Compiler may or may not inline the functions you marked as inline. It may also decide to inline functions not marked as inline at compilation or linking time.
2. Inline works like a copy/paste controlled by the compiler, which is quite different from a pre-processor macro: The macro will be forcibly inlined, will pollute all the namespaces and code, won't be easy to debug.
3. All the member function declared and defined within class are Inline by default. So no need to define explicitly.
4. Virtual methods are not supposed to be inlinable. Still, sometimes, when the compiler can know for sure the type of the object (i.e. the object was declared and constructed inside the same function body), even a virtual function will be inlined because the compiler knows exactly the type of the object.
5. Template methods/functions are not always inlined (their presence in an header will not make them automatically inline).
6. Most of the compiler would do in-lining for recursive functions but some compiler provides #pragmas-
microsoft c++ compiler - inline_recursion(on) and once can also control its limit with inline_depth.
In gcc, you can also pass this in from the command-line with --max-inline-insns-recursive
8) Pass-by-value VS Pass-by-reference
In many places we create the functions for small work/functionality which contain simple and less number of executable instruction. Imagine their calling overhead each time they are being called by callers.
When a normal function call instruction is encountered, the program stores the memory address of the instructions immediately following the function call statement, loads the function being called into the memory, copies argument values, jumps to the memory location of the called function, executes the function codes, stores the return value of the function, and then jumps back to the address of the instruction that was saved just before executing the called function. Too much run time overhead.
The C++ inline function provides an alternative. With inline keyword, the compiler replaces the function call statement with the function code itself (process called expansion) and then compiles the entire code. Thus, with inline functions, the compiler does not have to jump to another location to execute the function, and then jump back as the code of the called function is already available to the calling program.
With below pros, cons and performance analysis, you will be able to understand the “why” for inline keyword
Pros :-
1. It speeds up your program by avoiding function calling overhead.
2. It save overhead of variables push/pop on the stack, when function calling happens.
3. It save overhead of return call from a function.
4. It increases locality of reference by utilizing instruction cache.
5. By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining)
Cons :-
1. It increases the executable size due to code expansion.
2. C++ inlining is resolved at compile time. Which means if you change the code of the inlined function, you would need to recompile all the code using it to make sure it will be updated
3. When used in a header, it makes your header file larger with information which users don’t care.
4. As mentioned above it increases the executable size, which may cause thrashing in memory. More number of page fault bringing down your program performance.
5. Sometimes not useful for example in embedded system where large executable size is not preferred at all due to memory constraints.
When to use -
Function can be made as inline as per programmer need. Some useful recommendation are mentioned below-
1. Use inline function when performance is needed.
2. Use inline function over macros.
3. Prefer to use inline keyword outside the class with the function definition to hide implementation details.
Key Points -
1. It’s just a suggestion not compulsion. Compiler may or may not inline the functions you marked as inline. It may also decide to inline functions not marked as inline at compilation or linking time.
2. Inline works like a copy/paste controlled by the compiler, which is quite different from a pre-processor macro: The macro will be forcibly inlined, will pollute all the namespaces and code, won't be easy to debug.
3. All the member function declared and defined within class are Inline by default. So no need to define explicitly.
4. Virtual methods are not supposed to be inlinable. Still, sometimes, when the compiler can know for sure the type of the object (i.e. the object was declared and constructed inside the same function body), even a virtual function will be inlined because the compiler knows exactly the type of the object.
5. Template methods/functions are not always inlined (their presence in an header will not make them automatically inline).
6. Most of the compiler would do in-lining for recursive functions but some compiler provides #pragmas-
microsoft c++ compiler - inline_recursion(on) and once can also control its limit with inline_depth.
In gcc, you can also pass this in from the command-line with --max-inline-insns-recursive
8) Pass-by-value VS Pass-by-reference
- line_6 : Pass-by-value
- line_7 : Pass-by-reference
Pass-by-reference 可以用在function想要回傳(或改寫) 多個變數的值時. 因為 平常我們只能下
- X = Function(a,b,c);
這裡不管我們Function裡面寫得再複雜 也只能傳回一個值 assign 給X. 有了 Pass-by-Reference 事情就好辦了.
9) Function overloading
可以翻譯為重載, 以下三者都可以 只要傳入的data type 可以區分就行
- int f(int);
- int f(int, int);
- int f(int, double);
10) Function templates
重載的進階版, 避免寫太多重載函數. 可以自己寫個 library 預定義可延展的傳入data type
定義大概如下圖,
這裡value1, value2, value3 都是要同一個data type 如果要讓value1,2,3都屬於不同的data type 可以這樣定義,
template <class T1, class T2, class T3, class T4>;
T4 maxium(T1 value1, T2 value2, T3 value3){
....
}
正式的使用,
11) Recursive Functions
這裡value1, value2, value3 都是要同一個data type 如果要讓value1,2,3都屬於不同的data type 可以這樣定義,
template <class T1, class T2, class T3, class T4>;
T4 maxium(T1 value1, T2 value2, T3 value3){
....
}
正式的使用,
11) Recursive Functions
課裡簡單的提了一下, Recursive 最大的好處是讓軟體工程師寫程式的時候 很直覺, 直觀. 藉由Recursive把大的問題 不斷縮小 最後得到結果的方法. 應用的地方很多 比方說樹的深度優先搜索(DFS) 或 二分搜索(Binary search)
設計Recursive 的時候要注意,
- needs a condition to tell it when to stop(hit base case). 也就是要有 Exit point
- must guarantee that they will hit base case eventually. 要確定問題是不斷在變小
問題是比較慢, 另外有的程式語言會設定 stack的 limit 造成recursive 無法算出想要的答案
https://en.wikipedia.org/wiki/Recursion_(computer_science)
留言
張貼留言