将C++ 11代码连接到一些C回调,我必须传递const char * const *,即一个字符串数组.这是我的代码的简化版本:
int main(int,char**){
const int cnt = 10;
const char * const * names =
static_cast<const char * const *>(malloc( sizeof(char*) * cnt));
//... allocating names[0], etc. coming soon ...
the_c_function(names);
free(names);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以我研究了如何malloc在C++中使用,但我坚持free,因为它告诉我:"从'const void*'无效转换为'void*'[-fpermissive]"
我的第一反应是"呃?你为什么关心,所有你需要做的就是释放指针." 第二反应是把它扔掉.但这会被编译器拒绝:
free( const_cast<void*>(names) );
Run Code Online (Sandbox Code Playgroud)
这也是如此:
free( static_cast<void*>(acctnames) );
Run Code Online (Sandbox Code Playgroud)
例如"从类型'const char*const*'中的static static_cast'到'void*'类型".
什么做的工作是一个很好的"OLEÇ投:
free( (void*)(acctnames) );
Run Code Online (Sandbox Code Playgroud)
那是安全的,还是我在这里遗漏了什么?(valgrind告诉我"所有堆块都被释放 - 没有泄漏可能",这是一种安慰!)
PS在Linux上使用g ++ 4.8.1.
更新:解释为什么free()想要一个非常量指针在这里:无法释放C中的常量指针
(虽然我发现barak manos的答案在下面更清楚).
const_cast只能删除const和volatile限定词; 它无法改变指针类型.相反,static_cast可以更改类型,但不能删除顶级限定符.但是,void*从非const对象指针类型的转换是隐式的,所以这应该工作:
free( const_cast<const char**>(names) );
Run Code Online (Sandbox Code Playgroud)
更棘手的转换,需要a const_cast和a static_cast(甚至reinterpret_cast在奇怪的情况下).
邪恶ç投可以结合两种const_cast和static_cast,所以可以作为两个快捷方式.但是,这是一个坏主意,因为它更危险:如果你指定了错误的类型,那么它将强制进行转换reinterpret_cast,可能导致奇怪的运行时行为,其中更安全的强制转换将在编译时失败.
但是,这里不需要任何转换:转换为X*to X const*可以隐式完成,所以只需更改本地指针的类型:
const char ** names = static_cast<const char **>(malloc( sizeof(char*) * cnt));
the_c_function(names); // OK - adds const
free(names); // OK - no const to remove
Run Code Online (Sandbox Code Playgroud)
最后,因为这是C++,所以根本不需要使用malloc和指针(除非C API足够邪恶,要求从内存中获取内存malloc):
std::vector<const char*> names(cnt);
the_c_function(names.data());
Run Code Online (Sandbox Code Playgroud)