我的目标是保持被传递为的 pValueData 的完整值
常量字符*
那是不可能的。通过const 传递意味着它不能被修改,除非它最初不是常量。
例子:
char *ptr1 = new char[100]; // not const
char *ptr2 = new char[100]; // not const
int i = FunctionName(ptr1, ptr2, 123);
在这种情况下,您可以在技术上保留const_cast。但是为了什么?只需将您的函数参数更改为采用char *:
int FunctionName(char *pValueName, char *pValueData, long iMaxValueSize)
{
int iActualSiz = ProcessData(pValueData, iMaxValueSize);
// ...
}
但是,您很可能希望能够传递常量字符串。例如字符串文字:
int i = FunctionName("name", "data", 123);
字符串文字是不可修改的,因此需要您的函数采用char const *。稍后尝试修改它们会导致未定义的行为。
如您所见,错误出在一般架构和代码逻辑中。 您想修改某些内容,同时又不想允许修改它。
问题是:当ProcessData 完成后,你的pDataToStore 会发生什么? FunctionName 的调用者需要注意修改吗?还是只是FunctionName的内部业务?
如果只是FunctionName的内部业务,那么你可以保持其签名不变,让ProcessData修改一份传递过来的数据。这是一个简化的(不是异常安全的,没有错误检查)示例:
int FunctionName(const char *pValueName, const char *pValueData, long iMaxValueSize)
{
char *copy = new char[strlen(pValueData) + 1];
strcpy(copy, pValueData):
int iActualSiz = ProcessData(copy, iMaxValueSize);
// ...
delete[] copy;
}
好消息是您现在可以通过隐藏所有低级指针业务来大规模改进FunctionName 的界面。事实上,既然 C++ 标准类可以为您完成所有工作,为什么还要使用这么多指针呢?
int FunctionName(std::string const &valueName, std::string const &valueData, long maxValueSize)
{
std::vector<char> copy(valueData.begin(), valueData.end());
int actualSize = ProcessData(©[0], maxValueSize);
// ...
// no more delete[] needed here
}
std::vector<char> 自动分配足够的内存来保存valueData 的副本,并执行复制。它会在不再需要内存时完全自动释放内存,即使抛出异常也是如此。并且&copy[0](在 C++11 中可以写成copy.data())保证产生一个指向内部使用数据的指针,以便低级 C 函数可以修改向量的元素。
(我也借此机会删除了微软风格的匈牙利符号。这是 90 年代的一个失败的实验,你甚至错误地使用了它,假设前面的 i 应该是表示int。)
底线真的是:
如果您的代码中需要 const_castanywhere 以使其编译,那么在其他地方至少有一个 constmissing 或一个太多。const_cast 总是可以弥补另一段代码中的错误。它始终是一种解决方法,而不是预先设计的解决方案。