2011-07-26 34 views
13

注意:我使用的是g ++編譯器(這是我聽說的非常好,應該是非常接近標準)。當聲明對Ints數組的引用時,爲什麼它必須是對const指針的引用?


比方說,你已經宣佈的int數組:

int a[3] = { 4, 5, 6 }; 

現在讓我們假設你真的要聲明該數組(請不要介意,爲什麼,除了Bjarne的基準說,語言支持的話)。

案例1 - 如果你嘗試:

int*& ra = a; 

則編譯梁木,並說:

"invalid initialization of non-const reference of type `int*&' from a temporary of type `int*'" 

首先第一件事情,爲什麼是 '一個' 臨時變量(即不它在內存中的地方嗎?)......

反正精細,每當我看到一個非const的錯誤,我嘗試在一個const扔...

案例2 - 如果你嘗試:

int*const&rca = a; //wish I knew where the spaces should go (but my other post asking about this sort of protocol got a negative rank while many of the answers got ranked highly -- aha! there are stupid questions!) 

然後一切都很酷,它編譯,你會得到的數組的引用。

案例3 - 現在,這裏是另一回事,這將編譯:

int* justSomeIntPointer = a; //LINE 1 
int*& rpa = justSomeIntPointer; //LINE 2 

這也給了你原來的數組的引用。

所以這裏是我的問題:什麼時候靜態聲明的數組 的名稱成爲常量指針?我似乎記得一個int數組的名字也是一個int指針,但我不記得它曾經是一個const指針int ...

看起來好像情況1因爲聲明的參考(ra)不是const指針,這可能意味着'a'已經是一個const-pointer-to-int開頭。

似乎情況2的工作原理是因爲聲明的引用(rca)已經是一個const-pointer-to-int。

案例3也有效,它很整潔,但爲什麼?假定的指針指向int(即數組名稱'a')在什麼時候成爲一個常量指針?將它分配給int *(LINE 1)時會發生嗎?或者當您將該int *分配給int * &(LINE 2)時它會發生嗎?

希望這是有道理的。謝謝。

回答

27
int*& ra = a; 

int*是一個指針類型,而不是數組類型。所以這就是爲什麼它不會綁定到a,其類型爲int[3]

int* const& ra = a; 

的作品,因爲它相當於

int* const& ra = (int*)a; 

也就是說,臨時指針的賦值的右手邊是概念上創建,然後這個臨時勢必ra。因此,在端部,這是沒有優於:

int* ra = a; 

其中ra事實上是一個指針數組的第一元素,而不是到所述陣列的引用。

聲明到數組的引用的簡單方法:

typedef int array_type[3]; 
array_type& ra = a; 

的不是如-簡單的方法:

int (&ra)[3] = a; 

的C++ 11-簡單的方法:

auto& ra = a; 

靜態聲明數組的名稱成爲常量指針的哪一點?我似乎記得一個int數組的名稱也是一個int指針,但我不記得它曾經是一個const指針int ...

這是正確的問題要問!如果你明白陣列到指針的衰減何時發生,那麼你是安全的。簡單地說,需要考慮兩件事情:當任何一種「複製」的嘗試

  • 衰變發生(因爲C不允許數組直接複製)
  • 衰變是一種轉換,並能發生任何時候允許轉換:當類型不匹配時

第一種典型情況發生在模板上。所以給出template<typename T> pass_by_value(T);,然後pass_by_value(a)實際上傳遞一個int*,因爲int[3]類型的數組不能被複制

至於第二個,你已經看到它在行動:這種情況發生在你的第二個案例當int* const&無法綁定到int[3],但可以綁定到臨時int*,因此轉換髮生。

-2

a是一個臨時變量,因爲您在堆棧中聲明瞭它,而不是在使用malloc或new的堆上聲明它。

+0

所以被臨時變量總是const的? – Jimmy

+3

@Jimmy:臨時表達式並不總是const,但是語言禁止直接綁定到非const引用。數組'a'不是一個臨時的,但它是由數組到指針的轉換產生的指針,這是一個臨時的。 –

+0

在堆棧中聲明意味着'具有自動存儲持續時間',即當其包含的塊/對象確實不在「臨時」時超出範圍。很少有人考慮必須手動管理動態分配的對象才能成爲加分點。我們需要的最後一件事是關於爲什麼動態分配更好的另一個錯誤想法。這一點尤其糟糕,因爲它引發了_temporary_的錯誤定義,這個術語具有非常明確的,不同的含義。 –

0

什麼時候靜態聲明的數組的名稱成爲常量指針?我似乎記得一個int數組的名字也是一個int指針,但我不記得它曾經是一個const指針int ...

因爲你寫的值在cpp文件中,這就是爲什麼它是恆定的。

可以只使用:

const int *pToArray = a; 

const int *pToArray = (const int*)&a[0]; 
2

大多數人犯的非常大的錯誤(也是一個很好的面試問題)是他們認爲數組的名字相當於一個指針。這是不正確的。這個錯誤導致C程序中的許多錯誤,特別是連接錯誤,並且它們很難調試。不同之處在於:數組的名稱,是一個指針,它是結構的第一個元素,即數組。然而,數組名稱的類型不是pointertype,而是數組類型。另一方面,指針只是指向一件事物的指針,沒有其他信息。指針的類型是pointertype。數組類型具有其他一些屬性,如它知道它是否在堆棧上;因此,「暫時」。你的情況中的臨時錯誤來自一個檢查,它阻止了一個臨時變量被分配給一個引用。 const關鍵字將關閉。另一方面,Pointertype沒有「臨時」的概念。現在假設你想欺騙編譯器併爲堆棧中的東西分配一個引用。在這種情況下,你需要把它作爲一個指針。怎麼樣?

int * & ra = & a [0];

在上述情況下,您首先獲取值並使用&(操作符的地址)您製作pointerType。現在pointertype沒有關於它是否在堆棧上(臨時變量)的信息。但是,這將引用指向數組第一個元素的指針。 (所以只是一個指針類型,而不是一個數組類型)

1

如果你真的想要一個數組的引用,那麼你應該使用下列內容:

int a[3] = { 4, 5, 6 }; 
int (&ra)[3] = a; 

你正在嘗試與int *&創建是一個參考到一個指向int的指針。這不是同一類型。而當你用一個不能改變的值初始化參考(數組的地址)時,你必須聲明指針const(而不是int)。

1

您有整數數組:

int a[3] = { 4, 5, 6 }; 

現在,這一行:

int*& ra = a; 

創建一個指針的引用。由於您創建了一個臨時指針(從數組a轉換而來),編譯器會抱怨,因爲標準禁止將臨時對象分配給引用。

因此,要解決這個問題,你需要創建一個指針,然後將其分配給一個指針引用:

int *pa = a; 
int *& rpa = pa; 

經常提到可容納參考臨時工,但你已經發現了這一點。

你問什麼(約引用到一個數組) - 有關創建一個數組的引用最著名的例子是這樣的:

template< typename T, size_t N > 
size_t ArraySize(T (&)[ N ]) 
{ 
    return N; 
} 

這個函數接受一個數組的引用,並返回它的大小。

8

C++中的「數組」一詞拼寫爲括號[]。如果你想用C++聲明一個東西數組,你必須在你的聲明中有括號。如果你用星號*代替,你會得到一個指針。指針和數組是兩回事。

這是一個數組的引用:

int (&ra) [3] = a; 
相關問題