巨大 CString 的 C++ 串联

C++ Concatenation of Huge CStrings

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

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

这会导致多次分配,因此我们会遇到巨大的内存峰值。虽然这是在不同文件的多个线程上并行完成的。如果他们都凑齐我最终会得到 "Memory Exceptions".

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

对于编辑大字符串,您可能喜欢使用非连续类型 ropeunencoded_rope - 线程安全、写时复制或插入.

中间便宜

预先分配一个 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...

我会建议基本上与 Remy Lebeau 相同的东西,但使用一些不同的功能。我不确定 MFC/ATL 的哪个版本引入了 CString::Preallocate 功能,所以您可能遇到了没有此功能的 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.

来获得相同的分配行为