2011-11-06 138 views
0

我想澄清關於指針的一些問題,因爲這是我認爲在C++中很難的東西。當我宣佈一個指針,並把它傳遞給像一個函數:原始對象的C++指針和複製對象的指針

//just an example 
void showInt(int* numbers) 
{ 
    numbers += 3; 
} 

int main() 
{ 
    int* a = 10; 
    showInt(a); 

    return 0; 
} 

當我傳遞變量a的功能,我在實際傳遞的原始變量呢?還是創建一個變量的副本,然後將其傳遞給函數?

我如何知道我是否通過了一份副本或真實/原始副本?

+0

您需要該函數的名稱。 –

+1

@TommyA是的,對不起,我注意到並編輯了它:P – Danny

+5

無論你怎麼想'int * a = 10;'都行,不這樣做。 –

回答

3

你不能這樣做

int* a = 10 

這是沒有意義的,你的編譯器會告訴你錯誤。

當你這樣做:

//just an example 
void showInt(int* numbers) 
{ 
    numbers += 3; 
} 

int main() 
{ 
    int a = 10; 
    showInt(&a); 

    return 0; 
} 

有你傳遞的一個的ADRESS,然後添加這個ADRESS,所以沒有什麼變化。

如果更改:

numbers += 3; 

*numbers += 3; 

,那麼你就修改變量一個的價值。

還有一種方法來做到這一點: 只是改變

void showInt(int* numbers) 

void showInt(int& numbers) 

,那麼你可以使用

showInt(a); 

,你會修改值一個,並且複製將不會被創建。

0

a指的是指針,指向的值爲10。如果要將值10傳遞給方法,請使用*a。就目前而言,您將內存位置傳遞給頂層方法。在這種方法中,你通過3

增加它有沒有「複製」和「原始」本身:在main(),該10存在於內存中,並a具有指向它。在另一個方法中[沒有名字?]它需要一個int - 不是一個指針 - 所以如果你修改它,你不會改變指針的目標,只是參數(它像一個局部變量)。

希望能以某種方式提供幫助。

[編輯:你已經改變了現在採用int*參數代替int的第一種方法。這更有意義..讓我修改我的答案]

首先,我想澄清一下,代碼中沒有複製對象(實際上代碼中根本沒有實際的對象,只是內存中的一個int和一個指針通過並可能修改)。

showInt現在需要一個指針,正確。它會增加那個指針,在這種情況下指向一個未定義/無效的東西。如果你做numbers += 3那麼數字就會指向它最初指向的地方的3個字節,這一切都改變了。這隻在該方法的範圍內。

如果你這樣做:*numbers += 3那麼你會增加指針的目標,這意味着用13代替10。無論訪問什麼內存,即在main中,都會生效。

我可以建議你做一些閱讀到指針的好處VS 引用(如int&) - 一個體面的文章,你應該有一個相當不錯的「啊哈」的時刻:)

+0

Ugh;我也錯過了'int * a = 10;'創建一個指向地址10的指針,這是無效的。所以除了上面的內容,你可能的意思是'int v = 10; int * a =&v;' - 分配一個值爲10('v')的int然後指向它('a')。 –

+0

「呃;我也錯過了int * a = 10這一點;創建了一個指向地址10的指針,這是無效的。」並非真正無效,但我同意這可能不是他想要的。 –

+0

在某些嵌入式系統中,內存位置10可能指向一些IO寄存器或其他東西.. :) –

0

的指針你是傳遞指針的副本作爲參數,指針指向原始變量。因此,如果您取消引用指針,您將擁有原始值。記住一個指針基本上是一個地址,int *是一個整數的地址,如果你改變了指針的值,你改變了地址,這意味着指針會指向別的東西,如果你改變了這個值指針指向的內容,您將在指向同一對象時更改該值。

void ptrfunc(int *a) 
{ 
    *a = 10; 
} 

void reffunc(int &a) 
{ 
    a = 50; 
} 

void valfunc(int a) 
{ 
    a = 30; 
} 

int main() 
{ 
    int b = 20; 
    // Pass the point to b to the function, will alter the original. 
    ptrfunc(&b); 
    cout << b << endl; 
    // Pass a reference to b to the function, will alter the original. 
    ptrfunc(b); 
    cout << b << endl; 
    // Pass the value of b to the function, will not alter the original. 
    valfunc(b); 
    cout << b << endl; 
    return 0; 
} 

該功能將打印值10 INT第一COUT,和50中,因爲對象的值指出,和引用的下一個在功能被改變。valfunc更改b的副本的值,因此不會改變原始值。

0

讓我們通過你的例子:

void showInt(int* numbers) // (1) 
{ 
    numbers += 3;   // (2) 
} 

int main() 
{ 
    int* a = 10;   // (3) 
    showInt(a);    // (4) 
    return 0; 
} 

(1)numbers變量傳遞給這個函數變量的副本; (2)因爲(1)在numbers上所做的所有更改將僅保留在此函數內;因爲(1)所有在numbers上作出的更改將僅保留在此函數內;傳遞給這個函數的原始變量的值將保持不變!但請注意以下幾點:您不能更改傳遞給該函數的指針(a)的值,而是通過該指針的副本(即numbers),您可以更改它指向的值! 這是主要技巧 - 一旦你在函數內部有地址,你就可以在該地址寫入,並且在函數返回後這些更改仍然保留。在地址寫入包括指針解引用,但你幸運地沒有這樣做 - 我說'幸運',因爲你傳遞的地址只是內存中的任意地址(10)。如果您試圖在地址10處寫信,您的程序可能會崩潰。 (3)你已經聲明a是「指向int的指針」類型,所以它的值應該是某個int對象的地址。你在這裏犯了一個危險的錯誤,因爲你認爲10是一個int的有效地址,但你實際上並不知道該地址是什麼。

(4)您正在向函數傳遞變量a的副本。函數將其值存儲在numbers變量中並增加它。所以numbers現在包含地址13(不是某個整數變量的值是13的地址!)。 a但仍然相同,它仍然具有相同的值,10

你可能想是這樣的:

void showInt(int* numbers) 
{ 
    *numbers += 3;   // (1) 
} 

int main() 
{ 
    int a = 10;    // (2) 
    showInt(&a);    // (3) 
    return 0; 
} 

(1)功能,在保持numbers地址修改值。指針被取消引用。 (2)我們需要有一個int變量的有效地址,而不是隨機選取的地址(如10)。因此我們聲明int變量,a。它的地址是&a

(3)的地址a通過可變numbers傳遞給showInt和功能現在可以寫入到該地址(這是現在int對象的一個​​有效地址 - a)等修改的a值。函數返回時,a的值爲13.請注意,a的地址在此處的任何時間點都不會更改。