C++基本入門教程(八):函數指針。本站提示廣大學習愛好者:(C++基本入門教程(八):函數指針)文章只能為提供參考,不一定能成為您想要的結果。以下是C++基本入門教程(八):函數指針正文
比來工作比擬多,其實其實不忙,就是工作比擬影響思路,所以都沒心思寫文章了。
明天重要說說函數的一些根本情形吧,同時也說明一下老手最輕易含混的——甚麼時刻要用指針參數?
1、函數原型和函數界說
年夜家都曉得,C++界說函數之前,還須要聲明函數原型,關於習氣Java等其他高等說話的同伙來講,真心認為這很煩人。
以下代碼:
// 聲明函數原型
void startGame(int param);
// 函數界說
void startGame(int param)
{
// 各類邏輯
}
函數原型重要是給編譯器用的,在編譯的時刻會經由過程函數原型來檢討函數前往值、參數數目、參數類型等。
總而言之,便利編譯器,編譯器爽了,我們能力更爽。
但現實中,函數原型也便利我們疾速懂得某個類的功效。
這些很簡略,就不多絮聒了。
2、const限制符與指針
之前也有簡略引見過const,好比 const int num = 10; 那末num就是常量,弗成再次停止賦值操作了。
假如把const用在指針上呢?
int num = 10;
const int *p = #
// 編譯會報錯
*p = 100;
如上代碼,編譯的時刻就會報錯,由於指針p指向一個const int類型,這是一個常量。
所以*p的值是一個常量,不克不及被修正。
再來理一理,否則等會會凌亂的:
1.p是一個指針
2.p指向一個內存地址,這個地址裡寄存的是一個const int類型的值
3.*p代表是p指向的內存地址裡寄存的誰人值
4.所以,*p就是一個const int類型的值
5.綜上所述,*p不克不及再次被賦值。
這裡要辨別p和*p,這是兩個概念,一個是指針,一個是指針指向的值。
p是可以被再次賦值的,然則*p是不克不及被賦值的。
3、函數的指針參數
先來看看上面的代碼:
void notChangeNum(int num);
void changeNum(int* num);
int _tmain(int argc, _TCHAR* argv[])
{
int num = 10;
// 這個函數不會轉變num的值
notChangeNum(num);
cout << num << endl;
// 這個函數會轉變num的值
int* p = #
changeNum(p);
cout << num << endl;
return 0;
}
void notChangeNum(int num)
{
// 參數不是指針
num = 999;
}
void changeNum(int* num)
{
// 參數是指針
*num = 999;
}
這裡有兩個函數,一個是通俗參數(值傳遞),一個是指針參數(地址傳遞)。
第一個notChangeNum函數是不會轉變num的值的,由於num傳遞給函數時,是拷貝了一份新的值,本來的num是不受影響的。
當分開notChangeNum函數後,函數的num參數會被釋放。
第二個changeNum函數的參數是指針,我們都曉得,指針是指向某個內存地址的,所以,函數的參數指向的內存地址就是num的內存地址。
直接修正內存地址上的值,會影響本來的num,所以,分開changeNum函數後,num的值也會被轉變,終究值是999.
這就是指針參數的感化,某些情形下,我們願望函數裡對參數的修正可以或許真正發生影響。
4、為何要應用指針參數
為何要用指針作為參數呢?由於指針可以直接指向內存地址,可以直接在函數裡修正值,而且分開函數後依然失效。
說是這麼說,但,確定還有人會含混,為何呢?為何要如許呢?
好比,我們的函數參數是某個類:
void play(Sprite* sp) {
}
Sprite和Value都是Cocos2d-x經常使用的,這裡的參數為何是指針?
由於值援用的參數是會拷貝一份的,如許才不會影響本來的值,拷貝一份就會有額定的開支。
普通類的開支都比擬年夜(絕對於int、float等根本類型而言),所以拷貝一份不太適合。
並且我們經由過程都須要在函數裡轉變Sprite的坐標、年夜小等屬性,假如應用值傳遞的話,就沒法修正了(修正的只是拷貝的那一份)。
固然,這個還要看詳細項目標情形,我不絮聒了,太深刻欠好吹水。
5、不想拷貝,又不想值被修正,怎樣辦?
拷貝開支年夜,應用指針參數又極可能在函數被修正了值,怎樣辦呢?
這時候候就要用const限制符了,以下代碼:
void play(const Sprite* sp) {
}
如許在函數外部既不會修正sp指向的值,又可以免值傳遞的額定開支。
6、函數外部的變量分開函數時就會被釋放
我們之前說過,只需不是new出來的變量,那末,在分開感化規模後,就會被主動釋放。
然則,來看看這個函數:
int getNum() {
int num = 10;
return num;
}
既然變量分開感化規模後會被釋放,那末,num在分開getNum函數後,就會被釋放。
這時候候return num的意義安在呢?getNum函數真的能勝利獲得到數字10嗎?
謎底是確定的。
由於return 在前往num的時刻,現實上是拷貝了一份的,前往的是拷貝的值,釋放的是本來的變量。
這就是return的機密了。
然則,指針就不可了,看看上面的代碼:
// 假定有如許一個構造體
struct People {
int age;
};
People* getNewPeople() {
People nPeople;
nPeople.age = 20;
return &nPeople;
}
這個函數前往的是一個指向People構造體類型的內存地址。
依照return的規矩,前往的時刻現實上是拷貝了一份,但這個時刻拷貝的只是一個指針,也就是一個內存地址。
這個內存地址依然指向函數外部的nPeople變量。
所以即便getNewPeople函數勝利前往了一個指針,但這個指針指向的內存地址上的值依然是被釋放了。
也就是說,我們獲得的只是一個野指針。
7、停止
好了,這篇寫得有點蹩腳,太多內容了,我只是抽取部門來吹吹水~