一個傳值的問題”*”與”*”

1/*********************************************************
2* Desc:參數傳遞:使用引用傳遞指針和直接傳遞指針地址的區別
3* Author:charley
4* DateTime:2010-12-7 11:00
02***********************************************************/
03#include <iostream>
04using namespace std;
05??
06/*
07函數聲明
08*/
09void swapByRef(int *&,int *&);
10void swapByPoi(int *,int *);
11??
12int main(void)
13{
14????inti=10;
15????intj=20;
16????int*pi=&i; //pi指向i所在的內存地址
17????int*pj=&j;//pj指向j所在的內存地址
18??????
19????//通過引用傳遞參數,傳遞的是指針本身
20????cout<<"調用swapByRef()之前:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl;
21????swapByRef(pi,pj);
22????cout<<"調用swapByRef()之后:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl;
23??????
24????cout<<"**********************"<<endl;
25??
26????//通過指針來傳遞參數,傳遞的是指針地址
27????cout<<"調用swapByPoi()之前:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl;
28????swapByPoi(&i,&j);
29????//或者直接 swapByPoi(pi,pj);
30????cout<<"調用swapByPoi()之后:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl;
31??
32????getchar();
33????return0;
34}
35??
36/*
37通過引用傳遞參數:
38參數為整型指針的引用,
39引用是指針的一個別名,傳遞時不需要在內存中分配空間來接收參數
40參考:swapByRef(int &v1,int &v2)
41*/
42void swapByRef(int *&v1,int *&v2)
43{
44????int*temp=v1;//指針賦值,指針執行的地址變化了
45????v1=v2;
46????v2=temp;
47}
48??
49/*
50通過指針來傳遞參數:
51參數為整型指針變量
52內存存需要為形參分配空間來接收傳進來的指針地址
53參考:swapByPoi(int v1,int v2)
54*/
55void swapByPoi(int *v1,int *v2)
56{
57????inttemp=*v1; //操作指針指向的內容,指針執行的地址未變化
58????*v1=*v2;
59????*v2=temp;
60}

執行結果:

1

?

從結果可以看出:

1. swapByRef方法是直接交換參數的指針執行的地址,所以指針指向的內容也換了

2. swapByPoi方法只是操作指針指向的內容,指針執行的地址未變化

?

?

#include <stdio.h>

void swap(int x,int y)//這是錯誤的寫法
{
int temp;
temp=x;
x=y;
y=temp;
}

int main()
{
int a=5,b=8;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}

代碼很容易理解,就是交換2個變量a和b的值并輸出,但是運行后我們發現輸出結果不是"8 5"而依舊是"5 8",也就是說交換函數并沒有將2個變量的值交換,這是為什么呢?

我們知道,C語言中整型變量的形式參數傳遞的是值而不是地址,也就是形式參數實際上是復制了實際參數的值進入函數運算的,而被復制的實際參數的值并沒有改變。就這段代碼來說,就是形參x復制了a的值變成5,形參y復制了b的值變成8,然后在swap函數中進行交換,使得x=8,y=5,但實際上a和b的值并沒有被交換,這也就是為什么這段代碼并沒有實現交換的原因。

那么怎么解決呢?

先前我們說了C語言中整型變量的形式參數傳遞的是值而不是地址,那么現在我們就讓它傳遞地址,直接交換實際參數的值。

#include <stdio.h>

void swap(int *x,int *y)//使用指針傳遞地址
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}

int main()
{
int a=5,b=8;
swap(&a,&b);
printf("%d %d\n",a,b);
return 0;
}

我們使用指針變量來進行地址傳遞,形式參數為變量a和b的地址,swap函數直接交換a和b的地址所指向的值。這里一定注意形式參數傳遞的是地址而不是值

?

?

?

C++引用&和指針在作為形參時的區別

int n;

int &m = n;

在C++中,多了一個C語言沒有的引用聲明符&,如上,m就是n的引用,簡單的說m就是n的別名,兩者在內存中占同樣的位置,不對m開辟新的內存空間,對m的任何操作,對n來說是一樣的。

對于引用,有以下三條規則:

(1)引用被創建的同時必須被初始化(指針則可以在任何時候被初始化)。
(2)不能有NULL 引用,引用必須與合法的存儲單元關聯(指針則可以是NULL)。
(3)一旦引用被初始化,就不能改變引用的關系(指針則可以隨時改變所指的對象)。

?

假如在一個函數中動態申請內存空間,用指針和用引用作形參會得到不同的結果,如下面的例子:

void fun(int* b){? //用指針做形參
?b = (int*)malloc(sizeof(int)*3);

?for(int i=0; i<3; i++){
??a[i] = i;
?}
}

void fun(int* &b){??//用引用做形參
?b = (int*)malloc(sizeof(int)*3);

?for(int i=0; i<3; i++){
??b[i] = i;
?}
}

如果在main函數中定義了一個int型的空指針并分別作為實參傳入,如下:

int main(){
?int *a = NULL;

?fun(a);

?for(int i=0; i<3; i++){
??cout << a[i] << " ";
?}
?cout << "\n";

?return 0;
}

結果用指針的函數會出現內存訪問出錯,用引用的函數則運行正常并正確輸出1 2 3.

這是因為:

1.指針雖然是地址傳遞,但實際上也是在函數中又定義了一個新的指針讓其與傳入的指針指向同一地址。但兩個指針本身作為變量在內存中的存放地址是不同的,就是說這是兩個不同的變量,只是內容(即所指地址)相同。

2.在函數中對新定義的指針動態申請內存,但是當函數結束后,申請的內存的生命周期也就結束了,所以當回到主函數時,作為實參的指針地址和內容都沒有變化。仍然是個空指針,對其進行訪問自然出現了內存讀錯誤了。

假如在main函數中這樣寫:

int *a = (int*)malloc(sizeof(int)*3);

就不會出現內存讀錯誤了,但是輸出結果還是錯誤的,道理也是一樣的。

3.用引用作為實參傳入時,fun函數中的b其實就是主函數中a的別名(或者叫外號),反正就是操作完全相同,地址相同,內容相同的一個變量,所以當fun函數返回時,對b的操作在主函數中對a同樣有效。

?

再看一個例子:

int *a = NULL;

char* b = (char*)a;

?

int *a = NULL;

char* &b = (char*)a;

這一次是在編譯階段的區別:

用指針可以通過編譯,而用引用則不可以,提示類型轉換出錯。

?

通過這兩個例子可以看出,指針比引用靈活,也更加危險。

?

摘自『高質量c++編程』
條款一:指針與引用的區別
指針與引用看上去完全不同(指針用操作符’*’和’->’,引用使用操作符’.’),但是它們似乎有相同的功能。指針與引用都是讓你間接引用其他對象。你如何決定在什么時候使用指針,在什么時候使用引用呢?
首先,要認識到在任何情況下都不能用指向空值的引用。一個引用必須總是指向某些對象。因此如果你使用一個變量并讓它指向一個對象,但是該變量在某些時候也可能不指向任何對象,這時你應該把變量聲明為指針,因為這樣你可以賦空值給該變量。相反,如果變量肯定指向一個對象,例如你的設計不允許變量為空,這時你就可以把變量聲明為引用。

?

PS:引用在定義時不可加const,否則編譯出錯,在形參前面則可以加const以確保在函數中該變量不會被修改。

?

個人認為:其實形參建立的是一個新的地址,只是這地址是實參內容的一個COPY,假如實參為p,形參就為_p;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254604.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254604.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254604.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Classification分類halcon算子,持續更新

目錄ClassificationGaussian Mixture Models高斯混合模型add_class_train_data_gmmadd_sample_class_gmmclassify_class_gmmclear_class_gmmclear_samples_class_gmmcreate_class_gmmdeserialize_class_gmmevaluate_class_gmmget_class_train_data_gmmget_params_class_gmmget_…

spring boot 擴展之AutoConfigurationImportListener

最近閱讀spring boot源碼時發現&#xff0c;發現當spring使用ConfigurationClassParser加載使用Configuration注解類后&#xff0c;會使用AutoConfigurationImportSelector對加載的 Configuration注解的類進行一次過濾。當AutoConfigurationImportSelector過濾完成后會自動加載…

classpath: spring 中的查找方式

Spring可以通過指定classpath*:與classpath:前綴加路徑的方式從classpath加載文件,如bean的定義文件.classpath*:的出現是為了從多個jar文件中加載相同的文件.classpath:只能加載找到的第一個文件. 比如 resource1.jar中的package com.test.rs 有一個 jarAppcontext.xml 文件,內…

《高效程序員的45個習慣》-之一

敏捷開發是當下最流行的開發方法&#xff0c;它采用的是一種以人為核心、迭代、循序漸進的開發思想&#xff0c;值得你關注和學習。 最近我就閱讀了一本有關敏捷開發的書籍&#xff0c;《高效程序員的45個習慣》。 它以“舉反例”的方式來講述了敏捷開發中程序員應該運用的…

教你如何在 elasticsearch 中重建索引

序言 Elasticsearch 是一個實時的分布式搜索分析引擎。Teambition 使用 Elastisearch 作為搜索引擎&#xff0c;為用戶提供搜索服務&#xff0c;當我們決定存儲某種數據時&#xff0c;我們需要使用PUT /teambition創建索引&#xff0c;在創建索引的時候需要將數據結構完整確定下…

halcon控制算子Control,持續更新

目錄Controlassignassign_atbreakcasecatchcommentcontinueconvert_tuple_to_vector_1dconvert_vector_to_tupledefaultelseelseifendforendifendswitchendtryendwhileexecutable_expressionexitexport_defforglobalififelseimportinsertpar_joinrepeatreturnstopswitchthrowtr…

《CLR via C#》之線程處理——線程基礎

《CLR via C#》之線程處理——線程基礎 《CLR via C#》之線程處理——線程基礎windows為什么要支持線程線程開銷CPU發展趨勢CLR線程和Windows線程使用專用線程執行異步的計算限制操作線程調度和優先級windows為什么要支持線程 早期的操作系統只有一個執行線程&#xff0c;但同時…

《高效程序員的45個習慣》-之二

請您在閱讀本文之前&#xff0c;先了解《高效程序員的45個習慣》-之一。 每一期都會涉及15個話題&#xff0c;用3期來列出這45個習慣&#xff0c;每次不貪多&#xff0c;貪精&#xff0c;大家如果有空&#xff0c;一定要細細品味這15個習慣。 注意&#xff1a;每一個好的習…

MIME Type的介紹

轉載自&#xff1a; http://www.cnblogs.com/jsean/articles/1610265.html 一、 首先&#xff0c;我們要了解瀏覽器是如何處理內容的。在瀏覽器中顯示的內容有 HTML、有 XML、有 GIF、還有 Flash ……那么&#xff0c;瀏覽器是如何區分它們&#xff0c;決定什么內容用什么形式來…

spring boot之從零開始開發自己的網站

概述 首先要感謝兩位大神&#xff0c;該項目的想法來源自tale和MyBlog。 做了一些改造&#xff0c;增加了一些功能和一些代碼的重構&#xff0c;并且更換了博客主題。 關于項目&#xff0c;對于開發的練手項目&#xff0c;能夠工程化&#xff0c;嚴謹一些。 關于文檔&#x…

halcon深度學習算子,持續更新

目錄Deep Learning 深度學習Classification&#xff1a;分類apply_dl_classifierclear_dl_classifierclear_dl_classifier_resultclear_dl_classifier_train_resultdeserialize_dl_classifierget_dl_classifier_paramget_dl_classifier_resultget_dl_classifier_train_resultre…

python day5--正則表達式

#----正則表達式 import re elink <a href"(.*)">(.*)</a> info <a href"http://www.baidu.com">baidu</a> cinfo re.findall(elink,info) print (cinfo) import re print(re.search (r^a,abc\neee)) #預期結果 ^匹配字符開…

WCF系列教程之WCF客戶端調用服務

1、創建WCF客戶端應用程序需要執行下列步驟 (1)、獲取服務終結點的服務協定、綁定以及地址信息 (2)、使用該信息創建WCF客戶端 (3)、調用操作 (4)、關閉WCF客戶端對象 二、操作實例 1、WCF服務層搭建:新建契約層、服務層、和WCF宿主,添加必須的引用(這里不會的參考本人前面的隨…

《高效程序員的45個習慣》-之三

請您在閱讀本文之前&#xff0c;先了解《高效程序員的45個習慣》-之二。 每一期都會涉及15個話題&#xff0c;用3期來列出這45個習慣&#xff0c;每次不貪多&#xff0c;貪精&#xff0c;大家如果有空&#xff0c;一定要細細品味這15個習慣。 注意&#xff1a;每一個好的習…

負載均衡的那些事?

什么是負載均衡&#xff1f;1、負載&#xff1a;就是后端系統的承載能力。比如同等條件下&#xff0c;一個1核cpu-1G內存的機器的承載能力一般會比8核cpu-8G內存的機器要差&#xff1b;相同配置下&#xff0c;一個cpu利用率為80%的機器比30%的承載能力一般要差等等。2、均衡&am…

Develop內部函數,持續更新

Develop內部函數 目錄Develop內部函數dev_clear_objdev_clear_windowdev_close_inspect_ctrldev_close_tooldev_close_windowdev_disp_textdev_displaydev_error_vardev_get_exception_datadev_get_preferencesdev_get_systemdev_get_windowdev_inspect_ctrldev_map_pardev_map…

短信認證方案,用手機短信進行上網認證如何實現?

WFilter NGF的“Web認證”模塊&#xff0c;提供了一系列的上網認證解決方案。包括如下認證方式&#xff1a;本地用戶名密碼認證AD域用戶名密碼認證企業郵箱用戶名密碼認證Radius用戶名密碼認證微信WiFi認證Facebook Wifi認證除此&#xff0c;WFilter NGF還有一個“其他”的選項…

《高效程序員的45個習慣》-末篇

請您在閱讀本文之前&#xff0c;先了解《高效程序員的45個習慣》-之三。 每一期都會涉及15個話題&#xff0c;用3期來列出這45個習慣&#xff0c;每次不貪多&#xff0c;貪精&#xff0c;大家如果有空&#xff0c;一定要細細品味這15個習慣。 注意&#xff1a;每一個好的習…

【Qt開發】V4L2 API詳解 Buffer的準備和數據讀取

前面主要介紹的是&#xff1a;V4L2 的一些設置接口&#xff0c;如亮度&#xff0c;飽和度&#xff0c;曝光時間&#xff0c;幀數&#xff0c;增益&#xff0c;白平衡等。今天看看V4L2 得到數據的幾個關鍵ioctl&#xff0c;Buffer的申請和數據的抓取。1. 初始化 Memory Mapping …

halcon File文件算子,持續更新

目錄File文件Images圖像read_imageread_sequencewrite_imagedeserialize_imageserialize_imagelist_image_fileparse_filenameMisc混合體copy_filedelete_filefile_existsget_current_dirlist_filesmake_dirread_world_fileremove_dirset_current_dirObject對象deserialize_obj…