記錄一篇今天工作的思考。為什麼不建議函式的有太多引數?
今天做組內程式碼評審時,發現同事的程式碼有一個小問題,一個函式新增了一個引數後有了7個引數,而公司的編碼規範要求,函式的引數不許超過6個。
後來我就研究了一下,為啥不建議函式有太多引數呢?當然函式引數太多,不利於維護,學習成本比較高。除此之外,函式引數太多對效能也有一定的影響。
觀察引數傳遞方式
我做了一個實驗,觀察對含有6個、7個、8個引數的函式進行呼叫時,到底有哪些不同,測試程式碼如下:
#include <iostream>
void func6(int p1, int p2, int p3, int p4, int p5,
int p6)
{
}
void func7(int p1, int p2, int p3, int p4, int p5,
int p6, int p7)
{
}
void func8(int p1, int p2, int p3, int p4, int p5,
int p6, int p7, int p8)
{
}
int main()
{
func6(1, 2, 3, 4, 5, 6);
func7(1, 2, 3, 4, 5, 6, 7);
func8(1, 2, 3, 4, 5, 6, 7, 8);
return 0;
}
我們檢視彙編程式碼,來觀察呼叫時如何傳遞引數。
我們看一下func6的呼叫,全部通過暫存器傳遞。
0x00005555555551ce <+8>: mov r9d,0x6
0x00005555555551d4 <+14>: mov r8d,0x5
0x00005555555551da <+20>: mov ecx,0x4
0x00005555555551df <+25>: mov edx,0x3
0x00005555555551e4 <+30>: mov esi,0x2
0x00005555555551e9 <+35>: mov edi,0x1
0x00005555555551ee <+40>: call 0x555555555169 <func6(int, int, int, int, int, int)>
我們看一下func7的呼叫,引數1~6通過暫存器,引數7通過堆疊傳遞。
0x00005555555551f3 <+45>: push 0x7
0x00005555555551f5 <+47>: mov r9d,0x6
0x00005555555551fb <+53>: mov r8d,0x5
0x0000555555555201 <+59>: mov ecx,0x4
0x0000555555555206 <+64>: mov edx,0x3
0x000055555555520b <+69>: mov esi,0x2
0x0000555555555210 <+74>: mov edi,0x1
0x0000555555555215 <+79>: call 0x555555555188 <func7(int, int, int, int, int, int, int)>
我們看一下func8的呼叫,引數16通過暫存器,引數78通過堆疊傳遞。
0x000055555555521e <+88>: push 0x8
0x0000555555555220 <+90>: push 0x7
0x0000555555555222 <+92>: mov r9d,0x6
0x0000555555555228 <+98>: mov r8d,0x5
0x000055555555522e <+104>: mov ecx,0x4
0x0000555555555233 <+109>: mov edx,0x3
0x0000555555555238 <+114>: mov esi,0x2
0x000055555555523d <+119>: mov edi,0x1
0x0000555555555242 <+124>: call 0x5555555551a7 <func8(int, int, int, int, int, int, int, int)>
結論
gcc編譯器(gcc9),在x64環境下。函式呼叫時,前6個引數通過暫存器傳遞,超過6個後面的引數通過堆疊傳遞。而暫存器傳遞引數比堆疊傳遞效率高,所以建議函式引數不要超過6個。
學習c++還是要學習一些彙編的,可以解決很多問題啊。
最後,東北碼農,全網同名,求關注、點贊、轉發,謝謝~