二、面向過程的程式設計風格
阿新 • • 發佈:2021-01-28
技術標籤:Essential C++學習總結c++
- 將函式獨立出來的好處有:
1)以一連串函式呼叫操作取代重複編寫相同的程式程式碼,使程式易讀;
2)可以在不同的程式中使用這些函式;
3)可以更容易地把工作分配給協作開發團隊。
- 每個函式必須定義返回型別、函式名、引數列表和函式體四個部分。
- 函式必須先被宣告才能被呼叫(使用)。
- 函式的宣告讓編譯器得以檢查後續出現的使用方式是否正確(引數是否足夠、引數型別是否正確等)
- 函式宣告不必提供函式體,但必須指明返回型別、函式名和引數列表,即所謂的函式原型(function prototype)。
- 函式的定義包括函式原型和函式體。
- 成對的
/*
、*/
是多行註釋。 - 當用戶輸入一個不合理的值時,可以終止整個程式(稍顯極端)或丟擲異常(見第七章)。
- 標準庫的
exit()
函式用來終止程式。必須傳一個值作為程式結束時的狀態值。
#include <cstdlib>
//...
//以狀態-1結束程式
if(pos <= 0)
exit(-1);
- 函式只能返回一個值。題目“
fibon_elem()
是否計算出指定元素”關係到其返回值為true
或false
,而返回該元素的實際值可通過加入第二個引數完成,如:
//修正函式原型
bool fibon_elem(int pos, int &elem);
- 每個值型別都只能表示其值域(domain)中的最小至最大值間的某個值,超出即發生溢位(overflow)。
想知道某個型別的最小/最大值,可查詢標準庫中的
numeric_limits
class
#include <limits>
int max_int = numeric_limits<int>::max();
double min_dbl = numeric_limits<double>::min();
- 函式的宣告可以不寫出引數的名稱,引數名稱只有在函式內使用引數時才是必要的。
- 如果函式的返回型別不為
void
,必須在每個可能的退出點上將值返回。如果函式的最後一條語句不是return
,那麼最後一條語句之後便是該函式的隱式退出點,隱式退出點不返回任何數值則編譯出錯。 return;
語句不返回任何數值,只在返回值為void
時才被使用,可以提前結束函式的執行。- 兩種引數傳遞方式:傳址(by reference)和傳值(by value)。
- 當我們呼叫一個函式時,會在記憶體中建立起一塊特殊區域,稱為程式堆疊(program stack),提供了每個函式引數的儲存空間,也提供了函式所定義的每個物件的記憶體空間(這些物件也叫區域性物件local object)。一旦函式完成,這塊記憶體就會被釋放,也就是從程式堆疊中被
pop
出來。 - 將物件傳入函式,預設情形下它的值會被複制一份,成為引數的區域性定義。這種方式稱為傳值。
- 讓引數和傳入的實際物件產生關聯,即傳址,最簡單的方法便是將引數宣告為一個引用(reference):
void swap(int &val1, int & val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
- reference扮演著外界與物件之間一個間接手柄的角色。只要在型別名稱和reference名稱之間插入
&
符號,便是聲明瞭一個reference。
int ival = 1024; //物件,型別為int
int *pi = &ival; //指標pointer,指向一個int物件
int &rval = ival; //引用reference,代表一個int物件
int jval = 4096; rval = jval;
是將jval
賦值給rval
所代表的物件ival
。我們不能令rval
轉而代表jval
,因為C++不允許改變reference所代表的物件。pi = &rval;
是將ival
(即rval
所代表的物件)的地址賦值給pi
,並未令pi
指向rval
。- 面對reference的所有操作都和面對reference所代表的物件所進行的操作一模一樣。
- 使用傳址方式將物件作為函式引數傳入時,物件本身並不會複製出另一份——複製的是物件的地址。對該物件的任何操作都相當於對傳入的物件進行間接操作。
- 將引數宣告為reference的理由有:
- 可以直接對傳入的物件進行修改;
- 降低複製大量物件的額外負擔(直接傳入
vector
的地址比複製其中的所有元素更快)。
- 如下程式碼所示,我們聲明瞭一個reference to const vector,因為函式之中並不會更改
vector
的內容。加上const可以讓閱讀程式的人瞭解,我們以傳址的方式傳遞vector
是為了避免複製操作,而不是為了要在函式中對它進行修改:
void display( const vector<int> &vec )
{
for( int ix = 0; ix < vec.size(); ++ix)
cout << vec[ix] << ' ';
cout << endl;
}
- 也可以用pointer傳遞vector,與reference相同,都是傳遞物件的地址而不是整個物件的副本,唯一差別在於用法不同:
void display( const vector<int> *vec )
{
if( !vec )
{
cout << "display():the vector pointer is 0\n";
return;
}
for( int ix = 0; ix < vec->size(); ++ix) //vec->size()
cout << (*vec)[ix] << ' '; //(*vec)[ix]
cout << endl;
}
- pointer可能(也可能不)指向某個實際物件,當我們提領pointer時,一定要先確定其值並非0;而reference必定會代表某個物件,所以不需做此檢查。
- 傳址機制主要用於傳遞class物件,除非需要在函式內改變引數值,否則傳遞內建型別時一般不使用傳址方式。