最初的问题是我有一些数据可以从板块中保存和检索,并希望以下列方式使用辅助结构:
// this is how I want to use my struct for saving
void safeData()
{
Data data;
data.name = getNameToSave(); // returns const char*
save(data);
}
// ... and in the same way for writing.
void readData()
{
Data data;
read(data);
use(data);
}
......而
struct Data
{
const char* name;
// potentially many more data members
}
我现在绑定到(const)char *而不是std :: string,因为这应该与遗留代码一起使用。不幸的是,这会带来一个常量问题:
void read(Data& data)
{
// initial legacy free
free(data.name); // warning: can't convert from const char* to void*
// fill with some data
data.name = getNameFromPlate();
}
所以事情是这样的:因为我的读取数据检索方法如getNameFromSomewhere返回const char *我必须使我的struct成员也成为const。然而,这与写入使用冲突,因为在这种情况下它们必须是非const的。解决这个问题的最佳和最干净的方法是什么?
答案 0 :(得分:0)
最简洁的方法是Data
结构拥有 name
数据。所以当你分配它时你应该分配内存并做一个memcpy。这是确保a)不泄漏内存的唯一方法b)在完成数据之前不释放数据c)同时其他进程不会更改数据。
由于您无论如何都要复制,因此可以使用std :: string而不是const char*
来使其更易于管理。当您为const char*
分配时,std :: string将为您执行复制,您可以使用const char*
获得c_str()
,这样您仍然可以使用旧版架构。您无需进行切换,但从长远来看,这样可以更轻松地进行管理。
答案 1 :(得分:0)
您不仅存在常量问题,还存在所有权问题。除非API声明调用者在使用后必须释放getNameToSave()
的返回值,否则您应该不释放它。当您从文件中读取文件时,必须将其释放。
因此,更简单的方法是始终使用您在使用后始终免费使用的本地副本。由于您需要使用旧的const char *
代替std::string
,因此您最好继续使用旧的C库函数。这里最好的函数是strdup
,它自动分配内存并将旧字符串复制到其中。
另一种方法是将成员Data::name
的状态存储在布尔成员中:
struct Data
{
const char* name;
bool dyn; // must be freed if true
// potentially many more data members
}
然后您可以安全地使用:
if (data.dyn && (data.name != nullptr)) {
free(const_cast<char *>(data.name);
}