向一个常量双指针参数传递非常量指针参数。

7
在C++中,星号前的const修饰符意味着使用此指针时,所指向的值不能被更改,但指针本身可以指向其他内容。以下是示例:
void justloadme(const int **ptr)
{
    *ptr = new int[5];
}

int main()
{
    int *ptr = NULL;
    justloadme(&ptr);
}

justloadme函数不应该编辑传递的参数所指向的整数值(如果有的话),但可以编辑int*类型的值(因为第一个星号之后没有const修饰符)。但为什么我在GCC和VC++中都会得到编译器错误?

GCC:错误:从int**转换为const int**无效

VC++:错误 C2664:'justloadme':无法将参数1从'int **'转换为'const int **'。转换会导致限定符丢失

为什么会说转换会导致限定符丢失?难道不是增加了const限定符吗?此外,这难道不类似于strlen(const char*),我们向其传递一个非constchar*吗?


4
http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17 - Anycorn
1个回答

14

大多数情况下,编译器是正确的,而直觉则是错误的。问题在于,如果允许进行特定的赋值操作,则可能会破坏程序中的const-correctness:

const int constant = 10;
int *modifier = 0;
const int ** const_breaker = &modifier; // [*] this is equivalent to your code

*const_breaker = & constant;   // no problem, const_breaker points to
                               // pointer to a constant integer, but...
                               // we are actually doing: modifer = &constant!!!
*modifier = 5;                 // ouch!! we are modifying a constant!!!

被标记为[*]的那一行是违反规定的罪犯,出于特定原因而被禁止。该语言允许在最后一级添加const,但不允许在第一级上添加:

int * const * correct = &modifier; // ok, this does not break correctness of the code

1
虽然我们都认同编译器禁止对const变量进行修改,但是使用int * const * correct却会阻碍我们使用*ptr = new int[5];这个操作。那么我们该怎么办呢? - legends2k
1
问题很可能在于你想要做的事情与你所编写的代码不符。你想要完成什么任务?函数签名需要一个 const int **,但你传递了一个 int ** 并在函数内部将其视为 int **... 你真的想在签名中加上 const 吗? - David Rodríguez - dribeas
1
哦,现在我明白了!我试图做的是概念上错误的,所以是的,你是正确的。谢谢! - legends2k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接