2010-05-25 76 views
8

我會說明的代碼,我的問題:爲什麼從沒有指針的隱式轉換參考常量指針

#include <iostream> 

void PrintInt(const unsigned char*& ptr) 
{ 
    int data = 0; 
    ::memcpy(&data, ptr, sizeof(data)); 
    // advance the pointer reference. 
    ptr += sizeof(data); 
    std::cout << std::hex << data << " " << std::endl; 
} 

int main(int, char**) 
{ 
    unsigned char buffer[] = { 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, }; 

    /* const */ unsigned char* ptr = buffer; 

    PrintInt(ptr); // error C2664: ... 
    PrintInt(ptr); // error C2664: ...  

    return 0; 
} 

當我運行這段代碼(在VS2008)我得到這個:錯誤C2664:「PrintInt」:無法將參數1從'unsigned char *'轉換爲'const unsigned char * &'。如果我取消註釋「const」評論,它工作正常。

但不應將指針隱式轉換爲常量指針,然後引用?我期待這種方法奏效嗎?謝謝!

回答

10

如果指針被轉換爲const指針,如您所建議的那樣,那麼該轉換的結果是一個臨時值,一個右值。你不能將一個非const引用附加到一個右值 - 它在C++中是非法的。

例如,此代碼不會編譯由於類似的原因

int i = 42; 
double &r = i; 

即使型int是轉換爲類型double,它仍然不意味着你可以將一個double &參考的結果該轉換。

然而,一個const引用(即引用給const類型的引用)可以連接到一個右值,這意味着這段代碼可以編譯完全正常

int i = 42; 
const double &r = i; 

在你的情況,如果你宣佈你函數爲

void PrintInt(const unsigned char* const& ptr) // note the extra `const` 

代碼將被編譯。

+0

是啊,他說什麼:)函數簽名需要一個const引用:雖然通過引用傳遞指針有點沒有意義,因爲指針和引用需要是相同的大小...... – James 2010-05-25 20:29:40

+0

這是不正確的。引用比指針的大小更可能是零大小。 – Asher 2017-02-24 22:24:17

0

我想你需要:

void PrintInt(const unsigned char* const& ptr)

,如果你想通過引用傳遞一個const指針。

+1

通過reference-to-const傳遞指針有什麼意義?爲什麼不只是通過價值指針? – fredoverflow 2010-05-25 20:55:51

+0

@Fred正好,我不打擾;看到我的評論@AndreyT :) – James 2010-05-26 09:28:56

7

這將打破常量,正確性:

// if it was allowed 
const int x = 5; 
int *p; 
const int*& cp = p; // cp is a ´constant´ alias to p 
cp = &x;   // make cp (and p) point to a constant 
*p = 7;    // !!!! 

如果轉換被允許在上面的代碼編譯。一旦你初始化cpp(禁止在語言中),它們是別名。現在,您可以使用cp指向任何常量對象,因爲它是指向常量對象的指針。修改p指向的值也是有效的代碼,因爲它是一個指向非const對象的指針,但由於pcp是相同的,所以它將修改常量。

0

您不能將引用轉換爲指針,因爲指針可能爲空,而引用不能。換句話說,參考是一個指針更具限制性。引用總是一個有效的指針,但反過來並不總是對的。