怎么樣提高網站點擊率高明公司搜索seo
?
轉載知呼大佬06 - C++函數 - 知乎 (zhihu.com)
06 - C++函數
?
本期我們討論的是 C++ 中的函數。
函數到底是什么呢,函數就是我們寫的代碼塊,被設計用來執(zhí)行特定的任務,以后我們學習 class 類的時候,這些塊會被稱為方法,但是當我說到函數時,我們講的可不是 C++ 類里面的 方法。
01 函數能干什么
對我們來說,使用函數是很常見的,避免代碼重復。我們不想重復寫相同的代碼,當然,如果我們也可以復制和粘貼很多代碼,但會導致巨大的混亂,這也意味著如果我們決定改變一些代碼,我們必須在所有這些地方改變它,我們粘貼的地方,那維護這些代碼簡直就是災難,所以我們把我們要做的事情寫成一個函數,然后可以多次調用它。
如果需要的話,你可以認為函數有一個輸入,一個輸出,盡管他們可能并不需要這么做。我們可以為函數提供一定的參數,函數可以為我們返回值。
02 定義函數
假設我們想把兩個數相乘,我們想寫出這樣的一個函數。
?
我們對上面的代碼做一些詳細的解釋。
首先寫的是所謂的返回值?int
,也就是說,這就是這個函數的返回類型,因為是兩個整數相乘,這當然會得到一個整數 ;然后給出函數名?multiply
?,它有兩個參數?a
?和?b
?,這些就是我們要乘的數,它們的類型都是?int
。然后給出函數體,它會返回 a*b 。
這樣你就得到一個函數,它有兩個都是整數的參數,該函數的功能是返回兩者的乘積。
我們不一定非要提供參數,例如,我可以不提供任何參數,直接返回 5*8 ,這仍然是一個返回整數的函數,但它沒任何參數。
?
我們也可以讓函數不返回任何東西,我們通過寫?void?作為返回類型來實現,void 意思是啥也沒有,所以我們可以這樣做。
?
03 調用函數
如何調用這個函數呢?調用一個函數非常簡單,我們直接看下面的例子。
?
對上面的代碼我們做一些解釋。
首先我們定義了一個變量?result
,來裝這個結果,然后直接寫函數的名字加括號就可以完成調用函數,括號里面的數字就是函數需要的兩個參數,返回值 result 保存 a*b 的結果,最后我們將結果輸出到控制臺。按?F5
?來運行程序,你可以看到我們得到顯示是6,也就是2乘以3的結果。
04 為什么要用函數
所以,為什么要用函數呢?看起來代碼還更多了一些。
讓我們把情況說的更詳細些,假設我要做一堆的乘法,我想把它們都記錄到控制臺,在沒有函數的情況下,下面的情況這樣看起來會很亂。
?
如果你運行了這些代碼,你會發(fā)現我犯了一些錯誤,我想說的是,其實這種情況經常發(fā)生。人們復制和粘貼代碼塊, 然后忘記改變一個小細節(jié),在某些情況下程序如果正常運行的話,你就有可能注意不到,直到它在某個地方出錯了,你才會知道。
(你不會還沒發(fā)現錯在哪里吧?)
讓我們修正這些代碼。
?
這樣我們會得到正確的結果。
上面的多段代碼大部分內容基本差不多,基本的區(qū)別就是參與乘法的數字不同。這就很難受了。
讓我們?yōu)檫@個重復的過程創(chuàng)建一個函數。
先分析一下具體的需求。這個函數應該不需要返回值,它只需要輸出一些信息;這個函數需要兩個參數,就可以完成每段代碼中不同的部分;為了直觀的聯(lián)想到函數的功能,函數的名字就叫做?MultiplyAndLog
?吧,然后我們就有了下面這個函數。
?
函數定義好后,我們要做的就是調用這個函數。
?
如果啟動這個程序, 你可以看到,在這里可以獲得正確的值,這是一個很簡單的例子,我們獲得了一個非常干凈、易于閱讀的程序。
通過以上給分析過程,我們有效地證明了函數是真的非常重要的。你的目標應該是將你的代碼分開成很多函數。
然而, 有一件事我想強調,也不要把你的代碼每一行都拆成函數,對任何人都沒有好處的代碼,這很難維護,您的代碼將看起來凌亂不堪,它會讓你的程序變慢。
原因是每次我們調用函數時,編譯器生成一個call 指令,這基本上意味著,在一個運行的程序中,我們需要創(chuàng)建一個堆棧結構,這意味著我們必須把像參數這樣的東西推進堆棧,我們還需要將一個叫做返回地址的東西,然后我們要做的是跳到二進制執(zhí)行文件的不同部分,以便開始執(zhí)行我們的函數指令。為了將 push 進去的結果返回,我們得回去到最初調用函數之前。就像在內存中跳躍來執(zhí)行函數,跳躍和執(zhí)行這些都需要時間,這些會減慢我們的程序。當然前提是保持我們當前的函數是作為一個實際的函數,而不是做內聯(lián)inline
的工作(我們會在未來深入討論內聯(lián))。
我說這些都是因為不想讓你們對于每一行代碼都去創(chuàng)建函數,不要做那么搞笑的事情,編碼多了你才能明白哪里你會需要一個函數,但基本上如果你看到自己在多次做一項共同的任務,那么基本可以為此創(chuàng)建一個函數,函數的主要目的是防止代碼重復,我們不希望復制粘貼代碼。
05 其他的
現在我們回到代碼中,有些小伙伴會發(fā)現一個細節(jié),main 函數需要返回 int 類型的值,可是在 main 函數體中卻找不到 return 關鍵字。這樣操作是合理的嗎?
然我們做一個修改,驗證一些東西。
?
Ctrl+F7 編譯,我們得到了一個錯誤。
?
看起來有返回類型的函數的確必須有返回值。
原因是主函數實際上是一個特殊函數,只有主函數被豁免可以不返回值,它會自動假設你返回0。其他的函數必須要返回值。 main函數不寫返回值的操作只是現代 C 和C++ 的一個特性,可以讓你代碼保持的干凈一點。
好了,我們知道這必須返回一個值,剛才講的東西實際上 只適用于調試模式,如果我們在release 模式下編譯,這里你會看到我們沒有得到錯誤,這并不是說我們現在做的是正確的,因為如果我們真的要拿返回值值做某些事情的話,我們會得到 “未定義的行為” 的報錯信息,只是編譯器不會報錯,但是在調試模式下,編譯器就會顯示出錯。
后話
好了,這是一個基本的函數介紹,函數真的很有用。未來我還會寫很多函數,每個程序都是由一系列函數組成的,所以這是非常重要的,如果你不認為你完全理解函數是如何工作的,不用擔心, 因為在這個系列中我們會寫超級多的函數,你會掌握它的,最好的學習方法當然是多練習是吧。我們通常還將函數分解為聲明和定義,聲明通常存儲在頭文件中,我們在轉換單元或 CPP 文件中編寫定義,我將專門制作關于頭文件的一期,在那里會講到在頭文件中函數如何聲明。
?
?
?