C++中的引用與C語(yǔ)言的指針的指針運(yùn)用

C++中的引用與C語(yǔ)言的指針的指針運(yùn)用

引言

其實(shí)早就想寫這個(gè)筆記了耕腾,尤其是看到越來越多同學(xué)上課不怎么聽講課后多次犯了這個(gè)錯(cuò)誤后。心里有點(diǎn)捉急,于是想動(dòng)筆了拴竹。網(wǎng)上關(guān)于C++引用類型的說明其實(shí)有很多,也很通熟易懂剧罩,這里推薦一篇文章栓拜。那么在這里,我將結(jié)合自己的知識(shí)儲(chǔ)備進(jìn)行更有針對(duì)性的講解,希望同學(xué)們能夠耐下心來看完幕与。敘述中或許有些不太嚴(yán)謹(jǐn)或是沒用更加精確的術(shù)語(yǔ)的地方亦或是有些許錯(cuò)誤挑势,希望讀者諒解并提出。

我的講解順序是:

變量的作用域->C語(yǔ)言的傳參規(guī)則及指針傳參的錯(cuò)誤認(rèn)識(shí)->C++的引用類型->兩種解決C語(yǔ)言沒有引用類型的方法

變量的作用域

關(guān)于這一點(diǎn)我簡(jiǎn)單講啦鸣,基本規(guī)則就是變量作用域就是所在的花括號(hào)所包含的范圍潮饱。如:

for(int i=0;i<MAX;i++){
    ......
}

則i的作用域就是這個(gè)for循環(huán)。所以:

#include <stdio.h>

int main(void){

    for(int i=0;i<MAX;i++){
    ......
    }

    for(i=0;i<MAX;i++){
        ......
    }
    return 0;
}

編譯都會(huì)不通過诫给,因?yàn)閷?duì)于第二個(gè)for循環(huán)香拉,i是未定義的。你可以這樣簡(jiǎn)單理解:某個(gè)變量只在聲明時(shí)生成中狂,對(duì)所在花括號(hào)外面的語(yǔ)句塊沒有任何作用效果凫碌。等到執(zhí)行完到花括號(hào)末尾時(shí),變量就銷毀了胃榕。函數(shù)變量也是如此盛险,這里的函數(shù)里的變量指的是如下例

int Add(int a,int b){
    int c;
    c=a+b;
    return c;
}

中的a、b勋又、c苦掘。當(dāng)程序執(zhí)行到調(diào)用Add函數(shù)時(shí),變量a赐写、b鸟蜡、c生成并相應(yīng)的占用一塊內(nèi)存。當(dāng)函數(shù)執(zhí)行完時(shí)挺邀,變量a揉忘、b、c就被銷毀了端铛。

C語(yǔ)言的傳參規(guī)則及指針傳參的錯(cuò)誤認(rèn)識(shí)

上個(gè)學(xué)期學(xué)習(xí)指針時(shí)泣矛,老師肯定大都舉過類似這樣的一個(gè)例子:

#include <stdio.h>

void Plus(int a){
    a++;
}

void PPlus(int *a){
    (*a)++;
}

int main(void){
    int b=1;
    Plus(b);
    printf("%d\n",b);
    PPlus(&b);
    printf("%d\n",b);
    return 0;
}

運(yùn)行結(jié)果為:

1
2

不知道你們當(dāng)時(shí)是怎樣想的,我只記得很驚訝禾蚕,一直在問自己?jiǎn)柺裁囱侥啵浚炕幌繛槭裁唇Y(jié)果不是

2
3

經(jīng)過老師的講解哗总,我大概知道了。

因?yàn)镻lus函數(shù)傳參是傳值調(diào)用倍试,函數(shù)里面的a變量和主函數(shù)里面的b變量是獨(dú)立讯屈,占有不同的內(nèi)存,只是變量所儲(chǔ)存的值相等都是1县习。于是乎你函數(shù)里面的操作只是對(duì)函數(shù)變量a的操作涮母,對(duì)主函數(shù)里面的b變量沒用任何影響谆趾。于是乎就可以理解為函數(shù)變量a就是主函數(shù)變量b的復(fù)制品,對(duì)復(fù)制品的操作對(duì)原變量沒有任何影響叛本。

但是指針傳參好像就不一樣了沪蓬,因?yàn)樗?strong>傳址調(diào)用。通過函數(shù)指針變量a可以根據(jù)地址進(jìn)行改變主函數(shù)變量b的值来候。

于是乎跷叉,指針的傳址調(diào)用便深入大腦。于是同學(xué)們就記住指針調(diào)用不用加取址符這個(gè)原則营搅。

確實(shí)性芬,在上個(gè)學(xué)期應(yīng)對(duì)大部分問題時(shí)這句話幾乎屢試不爽。但是一到這個(gè)學(xué)期學(xué)了數(shù)據(jù)結(jié)構(gòu)時(shí)(特指教材用C++但是老師要求作業(yè)要使用C)剧防,漏洞百出植锉。那么問題出在哪里呢?

推薦兩本書《C與指針》和《C陷阱與缺陷》峭拘,廖勇老師推薦的俊庇,據(jù)說是屬于C語(yǔ)言圣經(jīng)級(jí)別的那種。扯遠(yuǎn)了······《C與指針》書中指出:C語(yǔ)言的傳參規(guī)則很簡(jiǎn)單鸡挠,就是傳值調(diào)用辉饱。

數(shù)組參數(shù)的傳址調(diào)用看起來似乎和傳值調(diào)用相悖。但是拣展,此處其實(shí)并無矛盾之處——數(shù)組名的值實(shí)際上是一個(gè)指針彭沼,傳遞給函數(shù)的就是這個(gè)指針的一份拷貝。

什么意思呢备埃?我們用代碼并結(jié)合圖畫來說明:

#include <stdio.h>
#include <string.h>

#define M 5

void Func(int *p){
    p[3]++;
    return;
}

int main(void){
    int a[M];
    memset(a,0,sizeof(int)*M);
    Func(a);
    for(int i=0;i<M;i++){
        printf("%d ",a[i]);
    }
    return 0;
}
函數(shù)調(diào)用過程
程序運(yùn)行結(jié)果

如前文我所講姓惑,傳值調(diào)用就是說形參(這里例子中指p)是實(shí)參(這里例子指a)的復(fù)制品,而指針作為參數(shù)其實(shí)并不違背傳值調(diào)用的原則按脚。p在調(diào)用函數(shù)時(shí)生成于毙,在函數(shù)結(jié)束時(shí)銷毀。但是卻確確實(shí)實(shí)對(duì)主函數(shù)里的數(shù)組a的所包含的元素的值進(jìn)行了改變辅搬。

其實(shí)唯沮,我比較喜歡這樣理解。比如第一個(gè)例子:

#include <stdio.h>

void Plus(int a){
    a++;
}

void PPlus(int *a){
    (*a)++;
}

int main(void){
    int b=1;
    Plus(b);
    printf("%d\n",b);
    PPlus(&b);
    printf("%d\n",b);
    return 0;
}

調(diào)用Plus函數(shù)時(shí)首先執(zhí)行了

int a=b;

語(yǔ)句堪遂。而調(diào)用PPlus函數(shù)時(shí)首先執(zhí)行了

int *a=&b;

語(yǔ)句介蛉。

例子

#include <stdio.h>
#include <string.h>

#define M 5

void Func(int *p){
    p[3]++;
    return;
}

int main(void){
    int a[M];
    memset(a,0,sizeof(int)*M);
    Func(a);
    for(int i=0;i<M;i++){
        printf("%d ",a[i]);
    }
    return 0;
}

當(dāng)調(diào)用Func函數(shù)時(shí)首先執(zhí)行了

int *p=a;

語(yǔ)句。

理解了以上部分溶褪,你就很容易理解這個(gè)學(xué)期學(xué)數(shù)據(jù)結(jié)構(gòu)時(shí)你一直不理解的問題了币旧。比如:

......
void List_Init(ListPtr p) {
  p = (ListPtr)malloc(sizeof(ListNode));
  if (p == NULL) {
    exit(0);
  };
  p->next = NULL;
  return;
}
......
int main(void){
    ListPtr head;
    List_Init(head);
    //printf("OK\n");
    List_Insert(head,......);
    //printf("OK\n");
    ......
    return 0;
}

你調(diào)試時(shí)發(fā)現(xiàn)程序在打印出第一個(gè)OK后就停止工作,于是就認(rèn)為時(shí)List_Insert函數(shù)有問題竿滨,于是絞盡腦汁結(jié)果還是找不出問題來佳恬,然后你就很煩,然后你就不想做了于游,然后你就希望去抄一下別人代碼交上去得了······其實(shí)你的錯(cuò)誤出在初始化函數(shù)······

List_Init函數(shù)

如此真相大白毁葱。

C++的引用類型

前面提到的文章講的就挺好的(戳這里)。

文章截圖

因?yàn)镃++不是C贰剥,所以傳參規(guī)則就不是僅限于傳值調(diào)用倾剿。我們結(jié)合具體實(shí)例講解:

#include <iostream>

using namespace std;


void PPPlus(int &a){
    a++;
    return;
}

int main(void){
    int b=1;
    PPPlus(b);
    cout<<b<<endl;
    return 0;
}

運(yùn)行結(jié)果:

2

其中調(diào)用PPPlus函數(shù)時(shí)發(fā)生如圖所示情況:

第一個(gè)例子

如果還沒理解引用,再看第二個(gè)例子:

#include <iostream>

using namespace std;


void PPPPlus(int *&a){
    (*a)++;
    return;
}

int main(void){
    int b=1;
    int *c=&b;
    PPPPlus(c);
    cout<<b<<endl;
    return 0;
}

運(yùn)行結(jié)果:

2

其中調(diào)用PPPPlus函數(shù)時(shí)發(fā)生如圖所示情況:

第二個(gè)例子

綜合兩個(gè)例子蚌成,我們可以清晰地看到前痘,所謂引用就是不像C那樣進(jìn)行復(fù)制,引用變量就是原變量地一個(gè)別名担忧,對(duì)引用變量的操作就是對(duì)原變量的操作芹缔。

于是乎,我們書上就用引用變量這個(gè)方法實(shí)現(xiàn)head的初始化:

......
void List_Init(ListPtr &p) {
  p = (ListPtr)malloc(sizeof(ListNode));
  if (p == NULL) {
    exit(0);
  };
  p->next = NULL;
  return;
}
......
int main(void){
    ListPtr head;
    List_Init(head);
    //printf("OK\n");
    List_Insert(head,......);
    //printf("OK\n");
    ......
    return 0;
}
List_Init函數(shù)

兩種解決C語(yǔ)言沒有引用類型的方法

但是不幸的是瓶盛,老師要求我們用C來實(shí)現(xiàn)所有題目最欠。那么有什么辦法呢?下面直接給出代碼:

代碼1

......
ListPtr List_Init() {
  ListPtr p ;
  p = (ListPtr)malloc(sizeof(ListNode));
  if (p == NULL) {
    exit(0);
  };
  p->next = NULL;
  return p;
}
......
int main(void){
    ListPtr head;
    head=List_Init();
    //printf("OK\n");
    List_Insert(head,......);
    //printf("OK\n");
    ......
    return 0;
}
List_Init函數(shù)

代碼2

這個(gè)方法就有點(diǎn)技巧了惩猫,不過我比較喜歡用這種方法芝硬,看似比較復(fù)雜但是好處還是挺多的。

void List_Init(ListPtr **p) {
  (*p) = (ListPtr)malloc(sizeof(ListNode));
  if ((*p) == NULL) {
    exit(0);
  };
  (*p)->next = NULL;
  return;
}
......
int main(void){
    ListPtr head;
    List_Init(&head);
    //printf("OK\n");
    List_Insert(head,......);
    //printf("OK\n");
    ......
    return 0;
}
List_Init函數(shù)

之所以喜歡用這個(gè)方法轧房,是因?yàn)檫@樣就保留了函數(shù)的返回值類型拌阴,我們可以令返回值為你想要的類型,比如bool或者status奶镶,以便后續(xù)調(diào)試迟赃。

其實(shí)指針的指針運(yùn)用可以完美去除帶頭節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。你們難道不覺得帶頭結(jié)點(diǎn)真的看起來很不舒服嗎厂镇?反正我就是有強(qiáng)迫癥捺氢,要我寫帶頭節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)我真的寫不下去。當(dāng)然并不是說頭結(jié)點(diǎn)沒一點(diǎn)好處剪撬,至少閱讀起來比較易懂摄乒。

后記

說句老實(shí)話,我覺得現(xiàn)在我們學(xué)校至少我們學(xué)院的同學(xué)們充滿了一種戾氣残黑。不怎么好描述馍佑,就是透露出一種很喪的心態(tài)。大學(xué)四年梨水,“革命”尚未結(jié)束拭荤,同志們?nèi)孕枧Π。?/p>

又到了推送小姐姐的時(shí)候了,送上新晉女神李惠利和一部劇《請(qǐng)回答1988》疫诽。


李惠利
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舅世,一起剝皮案震驚了整個(gè)濱河市旦委,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雏亚,老刑警劉巖缨硝,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異罢低,居然都是意外死亡查辩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門网持,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宜岛,“玉大人,你說我怎么就攤上這事功舀∑汲” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵辟汰,是天一觀的道長(zhǎng)遣铝。 經(jīng)常有香客問我,道長(zhǎng)莉擒,這世上最難降的妖魔是什么酿炸? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮涨冀,結(jié)果婚禮上填硕,老公的妹妹穿的比我還像新娘。我一直安慰自己鹿鳖,他們只是感情好扁眯,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翅帜,像睡著了一般姻檀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涝滴,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天绣版,我揣著相機(jī)與錄音,去河邊找鬼歼疮。 笑死杂抽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的韩脏。 我是一名探鬼主播缩麸,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赡矢!你這毒婦竟也來了杭朱?” 一聲冷哼從身側(cè)響起阅仔,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弧械,沒想到半個(gè)月后八酒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梦谜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袭景。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唁桩。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耸棒,靈堂內(nèi)的尸體忽然破棺而出荒澡,到底是詐尸還是另有隱情,我是刑警寧澤与殃,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布单山,位于F島的核電站,受9級(jí)特大地震影響幅疼,放射性物質(zhì)發(fā)生泄漏米奸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一爽篷、第九天 我趴在偏房一處隱蔽的房頂上張望悴晰。 院中可真熱鬧,春花似錦逐工、人聲如沸铡溪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棕硫。三九已至,卻和暖如春袒啼,著一層夾襖步出監(jiān)牢的瞬間哈扮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工蚓再, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灶泵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓对途,卻偏偏與公主長(zhǎng)得像赦邻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子实檀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 指針是C語(yǔ)言中廣泛使用的一種數(shù)據(jù)類型惶洲。 運(yùn)用指針編程是C語(yǔ)言最主要的風(fēng)格之一按声。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,430評(píng)論 3 44
  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,764評(píng)論 0 38
  • 1.語(yǔ)言中變量的實(shí)質(zhì) 要理解C指針恬吕,我認(rèn)為一定要理解C中“變量”的存儲(chǔ)實(shí)質(zhì)签则, 所以我就從“變量”這個(gè)東西開始講起吧...
    金巴多閱讀 1,739評(píng)論 0 9
  • I know it's love, but why my heart begins to tingle so mu...
    帶風(fēng)走路deFENG閱讀 161評(píng)論 0 1
  • 經(jīng)文:他們?cè)谀抢镌崃藖啿焙退拮尤隼衷谀抢镌崃艘匀龊退拮永偌宇砹希乙苍谀抢镌崃死麃啞?創(chuàng)49:31 一渐裂、...
    徐靜楓ruth閱讀 2,447評(píng)論 0 0