爲什麼不能將double ***
轉換爲const double ***
?爲什麼以下給我一個轉換錯誤從雙***到const雙***
void foo(const double ***d)
{
}
int main (int args, char*[] args)
{
double ***d;
/*initialize d */
foo(d);
}
爲什麼不能將double ***
轉換爲const double ***
?爲什麼以下給我一個轉換錯誤從雙***到const雙***
void foo(const double ***d)
{
}
int main (int args, char*[] args)
{
double ***d;
/*initialize d */
foo(d);
}
如果你的C標籤是可以相信的,GCC生成的類型爲你的榜樣和const double * const * const * d
兩者相差警告。在C++中,這是OP代碼中的一個錯誤,但slap-const-everywhere方法是合法的。
編譯器警告你的原因是指向指針(或進一步間接尋址)的指針允許通過修改參數指向的位置將指針返回給調用者。
如果指針的目標被聲明爲const,那麼被調用的函數會期望它放在那裏的值在返回時被視爲const。
傳遞T**
到const T**
這說明了爲什麼這是一個錯誤將是更簡單的情況下:
void foo (const char ** z)
{
*z = "A";
}
int main (int nargs, char** argv)
{
char* z = 0;
char** d = &z;
// warning in C, error in C++
foo (d);
// bad - modifies const data
z[0] = 'Q';
}
用C const
意味着數據不會改變。 C++中的const
表示數據不會公開更改--C++對象中的可變數據可能會更改。 AC編譯器可以優化其代碼,以便將某些const
數據緩存在某處,但由於可能存在可變性,C++編譯器無法執行此操作,因此具有較弱的限制,因此無法像上面那樣將常量數據返回到非const 。因此,在C++中,double***
可以轉換爲const double * const * const * d
,因爲額外的const
可防止返回不可修改的內存,但在C中,如果編譯器優化對其他位置的重複訪問,則會生成警告和可能的錯誤。
出於同樣的原因,對於**(指向指針的指針)也是如此。
此代碼也會產生這個錯誤,這是更清晰的看到爲什麼編譯器不會讓你做到這一點的位置:
double d = 0.0;
double * pd = &d;
const double ** ppd = &pd; // <--- Error
如果你能做到這一點,你可以有一個「常量」指向數據的指針(ppd),你可以通過改變可變值d來改變。這違反了const,所以編譯器不會讓你這樣做。
這不是原因,因爲這是合法的:double d = 0; double const * pd =&d ;,它還允許您通過更改局部變量來更改「const」指針。 – me22 2009-09-10 17:11:49
考慮d
指向黑匣子的指針。
編譯器可以將const添加到d
本身或黑盒,但不包括黑盒的內容。所以
void foo1(double ***d); /* ok, no casts needed */
void foo2(double *** const d); /* ok, no casts needed; const added to `d` itself */
void foo3(double ** const *d); /* ok, no casts needed; const added to the blackbox */
void foo4(double * const **d); /* oops, trying to change the insides of the blackbox */
void foo5(const double ***d); /* oops, trying to change the insides of the blackbox */
void foo6(double ** const * const d);
/* ok: d is a constant pointer to a constant blackbox */
的回答你的問題可以在http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
找到這意味着你應該使用const double * const * const * d
。
隨着 const的雙*** d僅d的值是常量。在C從雙一個到常量轉換雙*一個是合法的,同時從雙 b到 const的雙** b(或進一步間接)的轉化則不是。
因此從轉換雙皇冠d到常量雙*** D2,你可以做到以下幾點:
double*** d; const double* b = **d; const double** c = &b; const double*** d2 = &c;
當然使用常量雙皇冠d的由於非常量的間接性,這仍然值得懷疑。
有一個標記爲C和C++的問題,當關於什麼是錯誤和允許的不同的規則會產生一些混淆。 – 2009-09-10 11:36:09
@你是對的。我是這個例子的usigng C編譯器。這方面的規則真的不同嗎? – vehomzzz 2009-09-10 11:41:48