程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++基本入門教程(八):函數指針

C++基本入門教程(八):函數指針

編輯:關於C++

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、停止

好了,這篇寫得有點蹩腳,太多內容了,我只是抽取部門來吹吹水~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved