具有包含 void* 的结构的函数的 const 正确性和参数

And*_*nga 3 c++ struct pointers

我不会说我完全理解 const 正确性的想法,但至少可以说我理解它。所以,当我遇到这个问题时,我被难住了。有人可以向我解释一下吗?考虑以下代码:

\n\n
#include <iostream>\n\nstruct Test {\n    int someInt;\n    void * pSomething;\n};\n\nvoid TestFunc(Test * const pStruct) {\n    pStruct->someInt = 44;\n    pStruct->pSomething = "This is a test string"; // compiler error here\n}\n\nint main() {\n    Test t;\n    TestFunc(&t);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我用注释进行注释时,我从 gcc (4.5.3 for cygwin) 收到此错误:

\n\n
foo.cpp:10:24: error: invalid conversion from `const void*\' to `void*\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

这显然与结构包含 void* 这一事实有关,因为一些实验表明将结构更改为:

\n\n
struct Test {\n    int someInt;\n    char * pSomething;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

产生警告而不是错误。此外,保持结构不变但修改此行以包含以下强制转换会编译代码而不发出警告:

\n\n
pStruct->pSomething = (void*)"This is a test string"; // no error now\n
Run Code Online (Sandbox Code Playgroud)\n\n

鉴于我对const 正确性的理解,我不明白的是为什么编译器会发出此错误,“从 \xe2\x80\x98const void*\xe2\x80\x99 到 \xe2\x80\x98void* 的无效转换” \xe2\x80\x99 ” 到底是什么?既然函数定义上的 const 修饰符使得指针是常量,但它指向的内容却不是,为什么这会成为问题呢?我假设发生了某种隐式转换,正如最初编写的那样,因为字符串文字必须const char *转换为void *. 尽管如此,问题仍然存在,因为pStruct指向的内容并不是恒定的。

\n\n

作为参考,我在这里和这里阅读了const 正确性

\n

AnT*_*AnT 6

您观察到的错误与函数声明中使用的 const 限定符或您在代码中显式使用的任何 const 限定符完全无关。

问题与下面的最小示例相同

void *p = "Hello";
Run Code Online (Sandbox Code Playgroud)

遭受同样的错误。

在 C++ 语言中,字符串文字的类型是const char [N]。根据 const 正确性规则,它可以转换为const void *,但不能转换为void *。就这样。

更正式的正确错误消息是“无法从 转换为const char [22]void *或“无法从 转换const char *void *”,但显然编译器的内部工作原理首先执行转换为const void *,然后偶然转换为void *,这是为什么错误消息是这样措辞的。

请注意,C++ 语言的 const 正确性规则过去包含一个允许将字符串文字隐式转换为char *指针的异常。这就是为什么

char *p = "Hello";
Run Code Online (Sandbox Code Playgroud)

编译时仅显示警告,即使它像前面的示例一样违反了 const 正确性规则。该异常仅适用于char *类型转换,而不适用于void *类型转换,这就是前面的示例产生错误的原因。此特殊转换已在 C++03 中弃用,并在 C++11 中从语言中删除。这就是编译器发出警告的原因。(如果将编译器切换到 C++11 模式,则会出现错误。)