C++函数概念解析(1)
函數
一個典型的函數包含以下幾個部分
舉例如下
int fact(int ival) {int ret=1;while(val>1)ret*=val--;//這里先乘再減return ret; }| 形參 | ival |
| 實參 | ret |
| 返回類型 | int |
每當我們定義出一個函數,我們不能直接使用它,還得提供一個數值去調用它
int main() {int j=fact(5);cout<<"5! is "<<j<<endl;return 0; }執行函數首先隱式初始化,首先創建為一個叫ival的int類型變量,然后將它初始化為調用時所用到的形式參數
對于基元類型,復制初始化與直接初始化完全相同。對于具有構造函數的更復雜類型,除非復制構造函數被標記為顯式,否則復制初始化與調用值在=”之后的復制構造函數相同。我們一般可以認為拷貝初始化就是直接初始化。
形參與實參
實參是形參的初始值。正如上文所言,形參最開始是沒有值的,只是一個符號,在初始化開始之后,形參依次被其對應的實參初始化,但是編譯器卻并沒有這種對應關系,無需按照順序,可以直接求值。
函數的形參列表
形參列表可以為空,但不可以省略:
void f1();//隱式定義 void f2(void)//顯式定義為空時用void表示函數形參列表為空,是為了與C語言兼容,可以表示多個形參,中間使用逗號隔開,就算兩個形參的類型一樣,也得把兩個類型都寫出來:
int f3(int v1,int v2)函數的返回類型
大多數函數的返回類型都是各種類型值,也有少部分是返回void,或者返回函數或者數組的指針
關于局部對象
在C++中,名字有作用域,對象有生命周期
作用域:作用域(scope,或譯作有效范圍)是名字(name)與實體(entity)的綁定(binding)保持有效的那部分計算機程序。不同的編程語言可能有不同的作用域和名字解析。而同一語言內也可能存在多種作用域,隨實體的類型變化而不同。作用域類別影響變量的綁定方式,根據語言使用靜態作用域還是動態作用域變量的取值可能會有不同的結果。
生命周期:對象在程序執行過程中存在的時間
局部對象主要包含:
自動對象
一個函數在執行過程中,它的控制路徑經過變量自定義語句時創建該對象,當到達定義所在的末尾時銷毀該對象,整個過程期間存在的對象便稱為自動對象。這就導致如果我們在用傳遞給函數的實參初始化的形參對應的自動對象,如果變量本來就有初始值,就是用這個初始值初始化,若無初始值,便開始默認初始化。
局部靜態對象
有些時候這個這個變量的生命周期貫穿函數以及之后的調用時間,通俗來說就是這個變量作用很大,單單在自己的生命周期里面調用還不夠,需要多次調用,這樣我們就可以把它定義為static對象,它的銷毀是在程序終止的時候發生的
#include<iostream> using namespace std; size_t count_calls() {static size_t ctr=0;return ++ctr; } int main() {for(size_t i=0;i!=10;++i){cout<<count_calls()<<endl;}return 0; }關于函數聲明
函數在使用前必須要聲明,它只能定義一次,卻可以聲明多次
void print(vector<int>::const_iterator beg,vector<int>::const_iterator end)我們在編寫程序的時候,一般會把聲明放在主函數前面,函數的定義放在主函數后面,調用則在主函數里面進行,這樣做的目的是為了讓程序更加的規范化,否則你就得在一大堆函數定義里面去找函數聲明了
更加復雜的情況
C++支持分離式編譯,定義和聲明可以不在同一個文件中,這種情況下如果我們要編譯我們必須告訴編譯器我們的文件在哪里
指針形參
指針執行拷貝操作的時候,拷貝的是指針的值,拷貝之后兩個指針是不同的兩個指針,指針可以使得我們間接的訪問所指的對象,通過對指針值得修改可以間接的改變指針指向的對象的值
#include<iostream> using namespace std; int main() {int n=0,i=42;int *p=&n,*q=&i;*p=42;p=q;cout<<"p is "<<p<<endl;cout<<"i is "<<i<<endl;cout<<"n is "<<n<<endl; }輸出如下:
p is 0x61fe08 i is 42 n is 42避免引用拷貝
當容器對象比較大或者拷貝大類型對象的時候,拷貝被認為是一種低效的操作,甚至IO類型等個別類型壓根不支持拷貝操作。我們可以使用引用形參來來完成這個操作。
bool shorter (const string &s1,const string &s2) {return s1.size()<s2.size() }const形參和實參
int main() {const int ci=42;int i=ci;//拷貝的時候忽略了它是頂層ciint *const p=&i;*p=0;cout<<i<<endl; }使用實參初始化會忽略掉頂層const,這時把值傳給它的常量對象或者非常量對象都可以
void fcn(const int i)//可以讀取i,但是不能修改i void fcn(int i)//錯誤,重復定義了fcn(int)在參數傳遞的時候要注意:
把函數不會改變的形參定義成普通引用是一種常見錯誤
總結
以上是生活随笔為你收集整理的C++函数概念解析(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一文带你彻底搞懂C++中一些常见指针(形
- 下一篇: 如何在 Windows 中使用「iClo