亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

實例詳解C++中指針與引用的區(qū)別

 更新時間:2021年07月01日 14:41:55   作者:ZhiboZhao  
引用是C++引入的重要機制(C語言沒有引用),它使原來在C中必須用指針來實現(xiàn)的功能有了另一種實現(xiàn)的選擇,在書寫形式上更為簡潔,那么引用的本質是什么,它與指針又有什么關系呢?這篇文章主要給大家介紹了關于C++中指針與引用的區(qū)別,需要的朋友可以參考下

前言

在計算機存儲數(shù)據(jù)時必須要知道三個基本要素:信息存儲在何處?存儲的值為多少?存儲的值是什么類型?因此指針是表示信息在內存中存儲地址的一類特殊變量,指針和其所指向的變量就像是一個硬幣的兩面。指針一直都是學習C語言的難點,在C++中又多了一個引用的概念。初學時很容易把這兩個概念弄混,下面就來通過一些例子來說明二者之間的差別。

1、指針的聲明

上文中提到,指針和其所指向的變量就像硬幣的兩面,因此通過取址符號"&"我們可以找到變量的地址,通過解引用符號"*"可以找到地址內存放的變量值。

int data = 10; //聲明了一個變量data,并賦初始值10,存儲的值是int類型
int* p_data = &data; //找到 data 在內存中存放的位置,即p_data
cout << "地址為:" << int(p_data) << "\t 存放的值為:" << data << endl;

輸出結果為:

地址為:8191436  存放的值為:10

地址默認是16進制,我們在輸出時將其轉換成了int 類型,因此以十進制輸出。輸出結果翻譯過來就是:在地址編碼為8191436的位置存放了值為10的變量data,再進一步地說,data與*p_data 表示同一個東西。為了更有助于理解,我們繪制了下圖:

因此從本質上看,指針與普通的變量并沒有什么太大的區(qū)別,只是指針變量可以通過解引用的方式找到指針所對應的地址中存放的數(shù)值。假如定義如下:

int data = 10;
int* p_data = &data;  //定義指向 int 類型的指針 p_data, 存儲的是 int 類型的變量 data的地址,其
int** p_p_data = &p_data; //定義指向 int* 類型的指針 p_p_data, 存儲的是 int* 類型的變量 p_data的地址

cout << "p_data:" << p_data << "\t 存放的值為:" << *p_data << endl;
cout << "p_p_data:" << p_p_data << "\t 存放的值為:" << *p_p_data << endl;

輸出結果為:

p_data:00EFF96C         存放的值為:10
p_p_data:00EFF960       存放的值為:00EFF96C

從輸出結果可以看出,p_p_data中存儲的值就是p_data,而p_data中存儲的值就是data,很像”我愛她,她愛他“的這種橋段。下面我們就重點分析一下變量與指針之間的關系:我們在上述例子中把指針初始化為變量的地址,而變量是在編譯時分配的有名稱的內存,指針只是為可以通過名稱直接訪問的內存提供了一個別名。還拿上面這個例子:對程序員來說,變量10的名字就是data;而對于計算機來說,變量10就是存在 8191436 地址的數(shù)據(jù);實現(xiàn)程序員與計算機溝通的方式就是指針,通過對data取址讓程序員能夠明白計算機的存儲結構,同樣,通過對地址解引用,也能輕松地找到該地址中存儲的數(shù)據(jù)。在上述情況下,指針的出現(xiàn)顯得有些多余,然而指針的真正用武之地在于,在運行階段分配未命名的內存以存儲值,在這種情況下,只能通過指針來訪問內存。

最后關于指針聲明的一點建議:在聲明一個指針變量時,必須要指定一個確定的地址,否則聲明的指針變量不知道指向哪里,因此容易造成系統(tǒng)崩潰。

2、使用new來分配內存

內存四區(qū)之代碼區(qū),全局區(qū),棧區(qū)和堆區(qū)中提到過,new 會在堆區(qū)創(chuàng)建一個內存空間,其返回值就是該內存空間的地址,因此程序員的責任就是將該地址賦給一個指針。下面是一個示例:

int* p_data = new int; //在堆區(qū)開辟一個空間,并返回該內存空間的地址
*p_data = 10; //將向該內存中存儲數(shù)值10
cout << "p_data:\t" << p_data << "\t *p_data: " << *p_data << endl;

通過比較會發(fā)現(xiàn),new 后面指定了數(shù)據(jù)類型 int,同樣地,p_data 也被聲明為指向 int 的指針。這是因為,計算機的內存是以字節(jié)為存儲單位,不同類型的變量會占用不同的字節(jié),因此使用 new 時必須要告訴編譯器分配多少字節(jié)的存儲空間,并且接收的指針也必須與聲明的類型一致。輸出結果為:

p_data: 00D0D9A0         *p_data: 10

當處理大型數(shù)據(jù),比如數(shù)組時,通常會使用的一種方法是定義一個數(shù)組類型的數(shù)據(jù),在定義的時候分配足夠大的空間。但是這種做法太過于死板,但是當使用 new 時,如果在運行階段需要數(shù)組,那么則創(chuàng)建它,如果不需要則不創(chuàng)建,最重要的是可以在程序運行時選擇數(shù)組的長度。 下面就看一下如何使用 new 來創(chuàng)建動態(tài)數(shù)組。在C++中,數(shù)組名被解釋為數(shù)組地址,即數(shù)組第一個元素的地址。下面是一個實例:

int Arr[10]; // 定義一個包含10個int類型元素的數(shù)組
cout << "Arr:" << Arr << "\t&Arr[0]:" << &Arr[0] <<endl;

輸出結果為:

Arr:008FFAB4    &Arr[0]:008FFAB4

這種聲明方式只能在剛開始就聲明固定的數(shù)組長度,在C++中創(chuàng)建動態(tài)數(shù)組時,只需要將數(shù)組的元素類型和元素數(shù)目告訴給 new 即可,new 的返回值同樣是數(shù)組的首地址。

int ele_num = 10; //臨時指定數(shù)組內元素的個數(shù)
int* p_arr = new int [ele_num]; //根據(jù)臨時指定的元素個數(shù)創(chuàng)建數(shù)組

通過 new 在堆區(qū)開辟空間,由程序員管理釋放,因此當 new 的內存不用后,需要通過 delete 進行變量,使用 delete [] 來釋放開辟的數(shù)組空間。代碼如下:

int* p_data = new int;
*p_data = 10;
cout << "p_data: " << p_data << "\t*p_data:" << *p_data << endl;

int ele_num = 10;
int* p_arr = new int [ele_num];

for(int i = 0; i<9; i++)
 *(p_arr+i) = i+2;

cout << "p_arr:" << p_arr << "\t\t*(p_array):";
for(int i = 0; i<9; i++)
 cout << *(p_arr + i) << " ";
cout << endl;

delete p_data;
delete [] p_arr;

cout << "\n******使用delete釋放內存后......*******" << endl;
cout << "p_data: " << p_data << "\t*p_data:" << *p_data << endl;
cout << "p_arr:" << p_arr << "\t\t*(p_array):";
for(int i = 0; i<9; i++)
cout << *(p_arr + i) << " ";
cout << endl;

輸出結果如下:

p_data: 0082B1C8        *p_data:10
p_arr:0082BB58          *(p_array):2 3 4 5 6 7 8 9 10

******使用delete釋放內存后......*******
p_data: 0082B1C8        *p_data:-572662307
p_arr:0082BB58          *(p_array):-572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307

3、malloc 與 new 的區(qū)別

學過C語言的朋友都知道,在C語言中通過malloc函數(shù)開辟一塊內存空間,malloc的函數(shù)原型如下:

void* malloc(unsigned int numbytes);

從函數(shù)原型的參數(shù)可以看出,malloc 函數(shù)以字節(jié)數(shù)為參數(shù),開辟固定字節(jié)的內存空間。這與 new 就有了第一點不同:new 不需要自己計算字節(jié)數(shù),只需要給定內存中存儲的數(shù)據(jù)類型與元數(shù)個數(shù)即可。

從函數(shù)原型的返回類型可以看出,malloc 函數(shù)返回 void* 類型,需要我們在使用時自己指定指針類型。比如:

int* p_malloc = nullptr; // 創(chuàng)建一個指向int的指針
p_malloc = (int*) malloc(10); //將 malloc 的返回值強制轉換為 int* 類型

而 new 在使用時則不需要。總結看來,malloc 在使用時需要自己根據(jù)內存中的數(shù)據(jù)類型以及內存長度計算處所需要的字節(jié)數(shù),然后返回 void* 類型,需要使用對應類型的指針進行接收。而 new 在使用時只需要給定內存的長度與內存中數(shù)據(jù)的類型,編譯器會自動計算所需要的字節(jié)數(shù)。

4、引用的聲明與本質

C++中新增了引用作為已定義的變量的別名。引用的最主要用途是作為函數(shù)形參,這樣函數(shù)就可以使用原始數(shù)據(jù)而不是數(shù)據(jù)副本,這樣聽起來似乎與指針沒什么區(qū)別,我們還是從引用的聲明說起。

int data = 10;
int& p_data = data; //創(chuàng)建一個引用變量 p_data
cout << "data:" << data << "\tp_data:" << p_data << endl; //p_data 與 data 相當于一個變量的兩個名字

輸出結果為:

data:10  p_data:10

從輸出結果來看,p_data 與 data 就是一個變量的兩個不同叫法而已。引用必須在聲明時就為其指定初始值,而不能像指針一樣可以先聲明,再賦值。下面將引用作為函數(shù)的參數(shù)來進一步說明引用與指針的區(qū)別:

template <typename T> //定義一個模板函數(shù)
void swap(T a, T b){
 int temp;
 temp = a;
 a = b;
 b = temp;
}
int main(void){
 int a = 10, b = 20; 
 swap_value<int>(a,b); //首先進行值傳遞
 cout << "a:" << a << "\t\tb:" << b << endl;
 swap_value<int&>(a,b); //然后進行引用傳遞
 cout << "\na:" << a << "\t\tb:" << b << endl;
}

從上述代碼中可以看到,值傳遞和引用傳遞的形參都是一樣的,不同的是引用傳遞時,實參被聲明為引用,引用的用法與使用值一模一樣,輸出結果如下:

a:10            b:20
a:20            b:10

驚奇的發(fā)現(xiàn),引用傳遞改變了原始數(shù)據(jù)的值,這點與指針的用法一致,但是指針在書寫 swap 函數(shù)時應該這樣寫:

void swap(int* a, int* b){
 int temp;
 temp = *a;
 *a = *b;
 *b = temp;
}
swap(&a, &b); //調用格式

綜上發(fā)現(xiàn),引用其實就是變量的另一個名稱,它的用法與變量一模一樣,但是能在作為形參傳遞時,改變原始數(shù)據(jù)的值。除了這些用法上的區(qū)別,引用的本質其實就是一個指針常量,意味著指針指向的位置不可變,但是指針指向位置的值可變。即:

// 這兩者的語句是等效的,因此引用被當作指針常量來處理
int& p_a = a;  
int* const p_a=&a;

再補充一點小知識,關于 const 修飾符的問題,有些新手朋友來說很容易弄不清楚 const 修飾下什么是可變的,什么是不可變的。具體實例如下:

int data = 10, data2 = 20;
const int* p_data = &data; //修飾的是int,即 p_data 所指向的值不可變,而p_data可變
p_data = &data2;

int* const p_data2 = &data; //修飾的是int*,即 p_data 所指向的值可變,而p_data不可變
*p_data2 = data2;

引用即是第二種用法。

總結

到此這篇關于C++中指針與引用的區(qū)別的文章就介紹到這了,更多相關C++指針與引用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C/C++實現(xiàn)馬踏棋盤算法

    C/C++實現(xiàn)馬踏棋盤算法

    這篇文章主要為大家詳細介紹了C/C++實現(xiàn)馬踏棋盤算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++?構造函數(shù)和析構函數(shù)(Constructors?&?Destructors)詳解

    C++?構造函數(shù)和析構函數(shù)(Constructors?&?Destructors)詳解

    由于global?object的誕生比程序進入更早點,所以global?object的constructor執(zhí)行的時間更早于程序的進入點,所謂的default?constructor就是沒有指定任何的參數(shù)的constructor,這篇文章主要介紹了C++?構造函數(shù)和析構函數(shù)的相關知識,需要的朋友可以參考下
    2024-05-05
  • C語言字符串另類用法的實現(xiàn)

    C語言字符串另類用法的實現(xiàn)

    今天小編就為大家分享一篇關于C語言字符串另類用法的實現(xiàn),小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C語言實現(xiàn)個稅計算器

    C語言實現(xiàn)個稅計算器

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)個稅計算器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • c++中的system(

    c++中的system("pause")的作用和含義解析

    這篇文章主要介紹了c++中system("pause")的作用和含義,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-03-03
  • C語言實現(xiàn)順序表的基本操作的示例詳解

    C語言實現(xiàn)順序表的基本操作的示例詳解

    順序表是用一段物理地址連續(xù)的存儲單元依次存儲數(shù)據(jù)元素的線性結構,一般情況下采用數(shù)組存儲。本文將通過示例為大家講解一下順序表的基本操作,需要的可以參考一下
    2022-11-11
  • C語言聯(lián)合體Union特點及運用全面講解教程

    C語言聯(lián)合體Union特點及運用全面講解教程

    這篇文章主要為大家介紹了C語言聯(lián)合體Union特點及運用的全面講解教程有需要深度朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2021-10-10
  • C語言 數(shù)與串之間轉換的方法

    C語言 數(shù)與串之間轉換的方法

    C語言 數(shù)與串之間轉換的方法,需要的朋友可以參考一下
    2013-05-05
  • C++中STL的優(yōu)先隊列priority_queue詳解

    C++中STL的優(yōu)先隊列priority_queue詳解

    這篇文章主要介紹了C++中STL的優(yōu)先隊列priority_queue詳解,今天講一講優(yōu)先隊列(priority_queue),實際上,它的本質就是一個heap,我從STL中扒出了它的實現(xiàn)代碼,需要的朋友可以參考下
    2023-08-08
  • C++面向行輸入之get()與getline()實例詳解

    C++面向行輸入之get()與getline()實例詳解

    在c++里當我們輸入一個字符串時習慣用cin,但是cin只能讀取一段不含空格的字符串,如果我們需要讀取一段包含空格的字符串時,就需要用到getline()或get(),下面這篇文章主要給大家介紹了關于C++面向行輸入之get()與getline()的相關資料,需要的朋友可以參考下
    2021-10-10

最新評論