为什么不能将double ***
转换为const double ***
?
void foo(const double ***d)
{
}
int main (int args, char*[] args)
{
double ***d;
/*initialize d */
foo(d);
}
答案 0 :(得分:8)
如果要相信您的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中,如果编译器优化重复,它会生成警告和可能的错误访问其他地方的内存。
答案 1 :(得分:2)
您的问题的答案可以在http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
找到这意味着你应该真正使用const double * const * const * d
。
答案 2 :(得分:0)
答案 3 :(得分:0)
对于**(指针指针)也是如此,原因相同。
此代码也会产生此错误,并且更清楚地看到编译器为什么不允许您在此处执行此操作:
double d = 0.0;
double * pd = &d;
const double ** ppd = &pd; // <--- Error
如果你能够这样做,你可以有一个'const'指针指向数据(ppd),你可以通过改变可变值d来改变它。这违反了const,所以编译器不允许你这样做。
答案 4 :(得分:0)
考虑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 */
答案 5 :(得分:0)
const double *** d 只有 d 的值为常量的。在C中,从双 a 到 const double * a 的转换是合法的,而从双转换 b 到 const double ** b (或进一步的间接)不是。
因此,要从 double *** d 转换为 const double *** d2 ,您可以执行以下操作:
double*** d; const double* b = **d; const double** c = &b; const double*** d2 = &c;
当然,由于非const的间接性, const double *** d 的使用仍然值得怀疑。