2011-04-28 49 views
33

我輸入下面的例子:差分++

#include <iostream> 
double f(double* x, double* y) 
{ 
    std::cout << "val x: " << *x << "\n"; 
    std::cout << "val y: " << *y << "\n"; 
    return *x * *y; 
} 
double f2(double &x, double &y) 
{ 
    std::cout << "val x: " << x << "\n"; 
    std::cout << "val y: " << y << "\n"; 
    return x * y; 
} 
int main() 
{ 
    double a, b; 
    a = 2; 
    b = 3; 
    std::cout << f(&a, &b) << "\n"; 
    std::cout << f2(a, b) << "\n"; 
    return 0; 
} 

在功能f我聲明x和y爲指針,其中我可以通過使用*x得到的值。當致電f我需要傳遞我傳遞的參數的地址,這就是爲什麼我通過&a, &bf2是相同的,除了定義不同。

現在我的問題是:他們都實際上是同一個關於內存管理?兩者都沒有做任何傳遞值的副本,而是傳遞參考? 我想知道f2,因爲我無法讀出x的地址f2所以我知道更多關於x和y在f(我知道地址和價值)。

在此先感謝!

編輯:好感謝,做一些更多的研究後,我發現了一個非常有用的話題:

Pointer vs. Reference 還有谷歌編碼規則http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments這是相當useful我覺得(我現在明白一個鏈接,這是一種主題味道),使更多明確

+6

這不是C,這是C++。 – delnan 2011-04-28 09:50:56

+0

我在C中看到我總是用指針,好的,謝謝!到目前爲止還不知道! – tim 2011-04-28 10:01:03

+3

> Google風格指南 - 避免它。它在2008年已過時(相關日期),今天更糟。 – MSalters 2011-04-28 11:09:23

回答

38

f2正在參考它的參數,它實質上是一個別名您傳遞的參數。指針和引用的區別在於引用不能爲NULL。隨着f你需要通過地址(使用&運營商)你傳遞指針,就是當你通過引用傳遞你只是傳遞的參數,並創建別名的參數。

如果不打算更改函數內部的參數,並且打算更改它們時,請使用非const引用,因此,通過const引用(const double& ref)傳遞是首選。

當你需要能夠將NULL傳遞給你的參數時,主要使用指針,顯然如果指針在使用前不是NULL,你需要在函數內部檢查。

+0

爲什麼有人需要將Null傳遞給參數? – Weloo 2014-05-18 11:25:50

+1

那麼他們可能需要** ** **,如果需要傳遞null。顯然他們不會一直通過它。 – Ludwik 2014-07-15 06:25:50

+1

切割和清潔,很好的說明。謝謝 – pylover 2016-10-21 21:36:38

10

這只是句法糖,以避免每次引用參數時使用*。您仍然可以使用&擁有的x的地址f2

+4

+1爲「語法糖」:) – 2011-04-28 09:57:11

+8

我個人認爲它不僅僅是這一點。它聲明參數不能爲空,也不是可選的。用指針你永遠不會說,並且必須經常檢查。通過引用,函數簽名強制程序員的意圖,並導致更清晰的代碼更準確地反映該意圖。 – 2011-04-28 10:00:48

+0

你說得對,我沒有提到NULL值的情況。 – philfr 2011-04-28 10:02:44

2

您應該已經能夠在這兩個函數讀取x地址。

要因爲在f2這樣做,你當然必須前綴x的由&x參考爲雙,和你想的地址

引用和指針之間值得注意的區別是,前者不能爲空。你需要必須傳遞一些東西(有效),而當提供一個指針,你必須在文檔中指定是否允許/很好地定義傳遞NULL。

另一個區別是可讀性問題:使用引用而不是指針(如果可能的話)使得代碼不會與*->混淆。

7

尚未提及的另一個區別是,您無法更改引用所引用的內容。這在原始問題中顯示的函數調用示例中沒有太大的區別。

int X(10), Y(20); 
int *pX = X; 
int& rY = Y; 

*pX = 15; // change value of X 
rY = 25; // change value of Y 

pX = Y; // pX now points to Y 

rY總是指向Y,不能移動。

引用不能用於像指針這樣的簡單數組。

4

在我的腦海裏,函數的參數是總是按值傳遞。通過int很容易想象,通過double只是更大,通過structclass確實可以是非常大的。
但是,通過一個指針的東西,好吧,你只是通過值地址。(一個指針對於CPU來說通常是一個方便的大小,就像一個int一樣)。
引用非常相似,當然我認爲引用是指針,但是使用語法糖使它看起來像它的引用以價值傳遞。

你也可以把引用作爲const指針,即:

int i; 
int j; 
int* p = &i;   // pointer to i 
int* const cp = p;  // cp points to i, but cp cannot be modified 
p = &j;    // OK - p is modified to point to j 
*cp = 0;    // OK - i is overwritten 
cp = &j;    // ERROR - cp cannot be modified 

int& ri = i;   // ri refers to i 
ri = 1;    // i is overwritten 
ri = j;    // i is overwritten again 
         // Did you think ri might refer to j? 

所以,指針有雙重時間:這是在自己的權利的價值,但它也可以指向另一個值例如:*p
另外,引用參數意味着你不能在函數的生命週期中引用其他任何東西,因爲沒有辦法表達它。

的參考應該不能夠與null被初始化,但考慮到這一點:

void foo(int& i); 

int* p = 0; 
foo(*p); 

這意味着,在使用之前指針應進行檢查,但引用不能進行檢查。 foo()的執行可能會嘗試讀取或寫入i,這將導致訪問衝突。

在上述例子中的指針p已經在呼叫被用來foo之前檢查:

if (p) foo(*p); 
+0

這真的很有幫助,很好的例子。也許你可以給你的'void foo(int & i);'示例添加一個註釋來說明用NULL指針調用它是什麼錯誤。 – pfabri 2017-01-18 09:27:59