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