malloc/free in C++:为什么free不接受const void*,有更好的方法吗?

Dar*_*ook 5 c c++

将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的答案在下面更清楚).

Mik*_*our 9

const_cast只能删除constvolatile限定词; 它无法改变指针类型.相反,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_caststatic_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)