1. 程式人生 > >記憶體(傳值、傳址、傳引用)

記憶體(傳值、傳址、傳引用)

前言:

最近對記憶體產生了興趣、全是因為馬士兵老師的一句Master key、馬上要考二級了、大題建構函式比較多、形參有 int & x  這麼寫的、也有int *x 這麼寫的、還有普通 int x這麼寫的、我的乖乖這都是傳的什麼?

 int x 是 傳值、int *x  是傳址、 int & x是傳引用、那這三者傳引數都有什麼區別呢?

下面就用三個例子講解

宣告:下面堆疊的圖其實是不正確的、八個基本型別(byte、short、int、long、char、float、double、boolean)都是在棧裡面的、而下面的int型我把名字看做棧裡面、裡面的數值看做是堆裡面的、只是為了大家明白傳值、址、引用、的區別。

<span style="font-size:18px;">// C_TEST.cpp : Defines the entry point for the console application.
//
//
#include "stdafx.h"
#include "iostream"
using namespace std;//我是在VS2008裡面作的除錯,這裡需要匯入名稱空間STD
</span>

傳值

<span style="font-size:18px;">//傳值
	void swap1(int x,int y)
	{
		X = 3
		Y = 4
		cout<<"     傳值函式輸出:    "<<x<<"     "<<y<<endl;
		
		
	}
	void main()//入口點
	{
	 int a(1);
	 int b(2);
	swap1(a,b);
	cout<<"     外界值:      "<<a<<"     "<<b<<endl;
	
	}
	
//輸出:
	//傳值函式輸出:3 4
	//外界值: 1 2
</span>

堆疊圖(執行swap1前、執行swap1後)


是把實參的值賦值給行參   、那麼對行參的修改,不會影響實參的值   。

簡單的說就是、棧裡面的地址、堆裡面的物件都不是一個、比如我有首《chenchen絕唱》這首歌、我拷給了我的好同桌許小乖、她覺得特難聽、立馬就刪了、她刪了歌、我這還有、互不影響、還有一點要說明的就是、棧裡存放著指向物件的地址、所以物件複製出來是一樣的、但是堆裡的地址不一樣、所以ab棧的地址與xy棧的地址不一樣、就好似我的歌放在我的硬盤裡、考給同桌的歌放在她的硬盤裡、實體地址不一樣。

傳址

這裡把x、y做了交換、因為是傳址、所以更改了a 、b指向堆裡面的物件。

//傳址
	void swap2(int *x,int *y) //傳址呼叫
	{
	 //把主函式裡資料的地址傳了過來
	 //這裡改變了資料的地址,在主函式裡打印出a,b的時候,當然就發生了交換!
	   int temp;
	   temp = *x;
	   *x = *y;
	   *y = temp;
	   cout<<"     傳址函式內:    "<<x<<"     "<<y<<endl;
	}
	void main()//入口點
	{
	 int a(1);
	 int b(2);
	swap2(&a,&b);
	cout<<"     外界值:      "<<a<<"     "<<b<<endl;
	
	}
//輸出:
	//傳址函式輸出:0016FE04 0016FDF8
	//外界值: 2 1
這裡列印了x y 是 記憶體 地址、交換操作卻是對堆裡物件的操作。

堆疊圖(執行swap2前、執行swap2後)


是傳值的一種特殊方式,只是他傳遞的是地址,不是普通的如int   

那麼傳地址以後,實參和行參都指向同一個物件

對x、y的操作、互換、其實就是對a、b值的互換、因為他們都指向同一個物件、打個比方、有兩張一模一樣的藏寶圖、你一張、我一張、但是寶藏只有一個、我找到寶藏、拿走了、你再過去拿寶藏就沒有了、所以傳址只是把地址傳過來、用的物件還是那個物件、所以x y值的互換就是 物件 1 和2 值的互換、但是ab的指向的地址沒變、堆裡兩個物件的值卻互換了。

傳引用

<span style="font-size:18px;">//引用
void swap3(int &x,int &y)//傳引用
{
 //加了&之後,用地址引用了主函式裡面的資料值,說明x,y 的地址是a,b的地址~~,因而主函式裡面的a,b發生交換~~
   int temp;
   temp = x;
   x = y;
   y = temp;
   cout<<"     換址函式內:    "<<x<<"     "<<y<<endl;
}

void main()//入口點
{
 int a(1);
 int b(2);
 swap3(a,b);
cout<<"     外界值:      "<<a<<"     "<<b<<endl;

}

//輸出:
	//傳址函式輸出:21
	//外界值: 2 1
</span>

堆疊圖(執行swap3前、執行swap3後)


這裡的圖有可能不太對、但是我能這麼理解了、打個比方吧、一人拿著一張藏寶圖叫我去找寶藏、藏寶圖給了我、我去把寶藏拿給他、上圖棧裡的x y應該是指向a b 或者是a b的別名。

-----------------------------------------------------------------------------------

函式呼叫角度SEE傳值:

傳值:函式引數壓棧的是引數的副本。任何的修改是在副本上作用,沒有作用在原來的變數上。傳指標:壓棧的是指標變數的副本。當你對指標解指標操作時,其值是指向原來的那個變數,所以對原來變數操作。傳引用:壓棧的是引用的副本。由於引用是指向某個變數的,對引用的操作其實就是對他指向的變數的操作。(作用和傳指標一樣,只是引用少了解指標的草紙)  

-----------------------------------------------------------------------------------

總結:

         這兩天學了記憶體發現挺有意思的、說是換真還是一頭霧水、不是特別清楚、但是感覺真的對分析程式很有幫助、基礎知識嘛、要好好學。

參考文章

——————————————— 困-困 ———————————————

——————————chenchen——————————