C++ 巨大 CString 的串联

C++ Concatenation of Huge CStrings

本文关键字:CString 巨大 C++      更新时间:2023-10-16

我在遗留代码库中连接大型CStrings时遇到了问题。CStrings 可以包含 base64 编码的文件,因此可能很大。在几个点上,这些 CString 是这样连接的:

result += CString(_T("Some smaller String")) + Huge_CString + _T("Some smaller String");

这会导致多次分配,因此我们得到了巨大的内存峰值。尽管这是在不同文件的多个线程上并行完成的。如果它们都聚集在一起,我最终会得到"记忆例外"。

处理这个问题的最佳方法是什么。如果我能减少已经有帮助的分配数量。现在我不是在寻找完美的解决方案,而是在寻找一种减少峰值的方法。

对于编辑大字符串,您可能希望使用非连续类型ropeunencoded_rope - 线程安全、写入时复制或插入中间成本低的字符串类型

我会建议与Remy Lebeau基本相同,但使用一些不同的函数。 我不确定哪个版本的MFC/ATL引入了CString::P re分配功能,因此您可能被困在没有此功能的MFC/ATL版本上。

    CString result(_T("Initial string "));
    CString prefix(_T("Prefix string:"));
    CString suffix(_T(":Suffix string"));
    CString bigString(_T("This really isn't very big."));
    auto totalLength = result.GetLength() + prefix.GetLength() + bigString.GetLength() + suffix.GetLength();
    result.Preallocate(totalLength);
    result += prefix.GetString();
    result += bigString.GetString();
    result += suffix.GetString();

对 CString::GetString 的调用可能有用,也可能没有用。 只需将每个子字符串附加到 result 中,您可能会获得相同的分配行为。

预先分配所需级联长度的单个CString,然后将较小字符串中的数据复制到其内部缓冲区中,例如:

CString Huge_CString = ...;
LPCTSTR ss1 = TEXT("Some smaller String");
LPCTSTR ss2 = TEXT("Some smaller String");
int ss1_len = lstrlen(ss1);
int huge_len = Huge_CString.GetLength();
int ss2_len = lstrlen(ss2);
int concat_len = ss1_len + huge_len + ss2_len;
CString Concat_CString;
PXSTR buffer = Concat_CString.GetBufferSetLength(concat_len);
CString::CopyChars(buffer, ss1, ss1_len);
buffer += ss1_len;
CString::CopyChars(buffer, Huge_CSString.GetBuffer(), huge_len);
buffer += huge_len;
CString::CopyChars(buffer, ss2, ss2_len);
Concat_CString.ReleaseBuffer(total_len);
// use Concat_CString as needed...