2011-09-05 99 views
3

每次我嘗試編譯我的代碼,我得到錯誤:參數通過引用傳遞到指針問題

不能從「詮釋*」轉換參數1「詮釋* &」

它看起來像測試代碼這個:

void set (int *&val){ 
    *val = 10; 
} 

int main(){ 
    int myVal; 
    int *pMyVal = new int; 
    set(&myVal); // <- this cause trouble 
    set(pMyVal); // <- however this doesn't 
} 

我想在單個鏡頭中調用該函數而不創建指針的地方,只有理由通過它。而指針沒有構造函數,這樣的事情就不能完成。 set(int*(&myVal));。有沒有其他的方式來通過引用傳遞指針而不需要創建臨時變量?

編輯:順便說一句,我知道爲什麼代碼無法編譯(我只是傳遞可能是int而不是實際指針的地址)。問題是如何做到這一點。

+0

如果你不希望創建一個指針,爲什麼你需要的功能,採取指針(通過引用)?爲什麼不'set(int&v){v = 10;}'? – Beta

+0

因爲我的類正在存儲值,但這個值然後作爲指針傳遞給存儲此指針的另一個類。該指針必須通過引用函數中的指針參數來設置,否則傳遞的指針並不真正指向值,而是指向它的副本。在設置這個指針之前,我不想創建臨時指針只是爲了能夠傳遞它。這就是爲什麼我沒有介紹實際的問題,但只有那個類似於我的,並且更容易。 – Raven

回答

10

對非const的引用無法綁定到右值。 &運算符的結果是一個右值。看看the difference between lvalues and rvalues或閱讀a good C++ book

此外,在您的情況下,您不需要通過引用傳遞。以下情況也可以:

void set (int *val){ 
    *val = 10; 
} 

如果您要這樣做,則需要引用;

void set (int*& val){ 
    val = new int; //notice, you change the value of val, not *val 
    *val = 10; 
} 
+0

所以'int * const&p'是對常量指針的引用,所以它可以被賦值爲右值,對吧? – Raven

+2

@Raven:是的,這是正確的。但不需要通過引用const來傳遞內置類型。它不如傳遞價值更有效。對於用戶定義的類型,最好通過引用傳遞給const –

2

&myval是(類型int*的)右值,因爲它是一個臨時性的。它是一個指針,但不能修改它,因爲它只是在飛行中創建的。但是,您的函數set需要非const引用,所以您不能將它傳遞給臨時對象。

相比之下,pMyVal是一個命名變量,因此是一個左值,所以它可以作爲非常量引用傳遞。

+0

我會說'&myval'的類型是int * const&'。 – starblue

+0

對不起,但這在許多方面都是不正確的和誤導性的。首先,'const int *&'是「指向const int的指針的引用」,而不是「對常量指針的引用」。其次,對const和rvalues的引用有區別(rvalues_don't_沒有'const T&'類型)。第三,一個對象不需要被命名爲左值。 – jpalecek

+0

@starblue:是的,我的錯。修正了,謝謝! –

0

問題是,int*&val只能通過一個左值,其結果是& myVal不是。通過將簽名更改爲void set(int* const& val),它告訴編譯器您不會更改指針的值。

但是,你通常不會那樣做,只是因爲如果你不打算改變指針的值,那麼通過值傳遞指針是傳遞值最直接的方法。如果你要改變指針的值,那麼你需要創建一個臨時接收結果。

0

可以看到以下示例代碼:

#include <iostream> 
using namespace std; 

void change(int*& ptr) { 
    cout << endl; 
    cout << "==================change(int*& ptr)====================" << endl; 
    cout << " &ptr = " << &ptr << endl; 
    cout << " ptr = " << ptr << endl; 
    cout << "=======================================================" << endl; 
    cout << endl; 
    *ptr *= *ptr; 
} 

int main(void) { 
    int* ptrNumber = new int(10); 

    cout << endl; 
    cout << "&ptrNumber = " << &ptrNumber << endl; 
    cout << "ptrNumber = " << ptrNumber << endl; 
    cout << ">>> *ptrNumber = " << *ptrNumber << endl; 
    change(ptrNumber); 
    cout << "<<< *ptrNumber = " << *ptrNumber << endl; 
} 

我安裝Cygwin和用於克++編譯上述源代碼,二進制文件是out_pointer.exe。 執行out_pointer。exe文件,輸出如下:

$ ./out_pointer.exe 

&ptrNumber = 0x28ac3c 
ptrNumber = 0x800102c0 
>>> *ptrNumber = 10 

==================change(int*& ptr)==================== 
    &ptr = 0x28ac3c 
    ptr = 0x800102c0 
======================================================= 

<<< *ptrNumber = 100 

從上面的輸出,我們看到

&ptrNumber = &ptr 

所以,PTR是ptrNumber的別名。您可以通過修改ptr來修改函數void change(int * & ptr)中的ptrNumber。例如,您可以PTR指向如下另一個存儲位置:

#include <iostream> 
using namespace std; 

void change(int*& ptr) { 
    cout << endl; 
    cout << "==================change(int*& ptr)====================" << endl; 
    cout << " &ptr = " << &ptr << endl; 
    cout << " >>> ptr = " << ptr << endl; 
    ptr = new int(20); 
    cout << " <<< ptr = " << ptr << endl; 
    cout << "=======================================================" << endl; 
    cout << endl; 
} 

int main(void) { 
    int* ptrNumber = new int(10); 

    cout << endl; 
    cout << ">>> &ptrNumber = " << &ptrNumber << endl; 
    cout << ">>> ptrNumber = " << ptrNumber << endl; 
    cout << ">>> *ptrNumber = " << *ptrNumber << endl; 
    change(ptrNumber); 
    cout << "<<< &ptrNumber = " << &ptrNumber << endl; 
    cout << "<<< ptrNumber = " << ptrNumber << endl; 
    cout << "<<< *ptrNumber = " << *ptrNumber << endl; 
} 

新的輸出:

$ ./out_pointer.exe 

>>> &ptrNumber = 0x28ac3c 
>>> ptrNumber = 0x800102c0 
>>> *ptrNumber = 10 

==================change(int*& ptr)==================== 
    &ptr = 0x28ac3c 
    >>> ptr = 0x800102c0 
    <<< ptr = 0x80048328 
======================================================= 

<<< &ptrNumber = 0x28ac3c 
<<< ptrNumber = 0x80048328 
<<< *ptrNumber = 20