将变量传递给具有常量参数的函数

SAN*_*IKA 6 c++ pointers const-correctness

我很困惑。我看到当代码是这样的

void fun(const char **p) { }
int main(int argc, char **argv)
{
   fun(argv);
   getchar();
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

它显示error: invalid conversion from 'char**' to 'const char**'

但是当代码像这样

void test(const char *p) { }
int main()
{
    char *c = new char('a');
    test(c);
}
Run Code Online (Sandbox Code Playgroud)

然后就没有编译错误了。两个代码有什么区别?
为什么第二段代码可以将变量传递给常参数的函数?

Pas*_* By 5

指向指针的指针很奇怪。以这个例子为例

\n
const int i = 42;\nint* p;\nconst int** pp = &p;  // safe?\n*pp = &i;  // *pp refers to p, but has the type const int*\n*p = 420;  // !!\n
Run Code Online (Sandbox Code Playgroud)\n

显然,仅仅通过分配指针是无法击败的,因此从到 的const转换是非法的。T**const T**

\n
\n

但等一下,为什么要转换T*const T*合法的呢?

\n

是的,这是因为每个都T可以被视为一个const T。Aconst T只是 的一个限制T。对 的任何操作都const T将是非法的T。如果您将类型视为表示对象上的一组合法操作,则const T表示 的子集T

\n

然而,限制被指者会对指针产生相反的效果。Aconst T*不是 的子集T*。AT*只能指向非常量T,而const T*可以指向任意 T。就指针本身的赋值而言,是\xe2\x80\xa0const T*的超集,而不是相反。T*

\n

T**那么为什么从到 的转换不const T**合法呢?因为T*不是 的超集const T*:并非所有都T*可以被视为const T*,如开头片段所示。

\n

\xe2\x80\xa0但是如果取消引用指针,则const T是 Again 的子集T,因此const T*T*不是彼此的子集。

\n