C++字符串的级联

C++字符串的级联,c++,concatenation,c-strings,C++,Concatenation,C Strings,我遇到了一个在遗留代码库中串联巨大CString的问题。CString可以包含base64编码的文件,因此可能非常庞大。在几个点上,这些CString是这样连接的: 结果+=CString_TSome较小字符串+巨大_CString+_TSome较小字符串 这会导致几次分配,因此会出现巨大的内存峰值。尽管这是在不同文件的多个线程上并行完成的。如果它们都在一起,我将最终得到内存异常 最好的处理方法是什么。如果我能减少已经有帮助的拨款数量。现在我不是在寻找完美的解决方案,而是寻找一种减少峰值的方法。

我遇到了一个在遗留代码库中串联巨大CString的问题。CString可以包含base64编码的文件,因此可能非常庞大。在几个点上,这些CString是这样连接的:

结果+=CString_TSome较小字符串+巨大_CString+_TSome较小字符串

这会导致几次分配,因此会出现巨大的内存峰值。尽管这是在不同文件的多个线程上并行完成的。如果它们都在一起,我将最终得到内存异常


最好的处理方法是什么。如果我能减少已经有帮助的拨款数量。现在我不是在寻找完美的解决方案,而是寻找一种减少峰值的方法。

对于编辑大型字符串,您可能喜欢使用线程安全的非连续类型rope或-string类型,即写即复制,或者插入中间比较便宜。

对于编辑大字符串,您可能希望使用线程安全、写时复制或插入中间比较便宜的非连续类型rope或-string类型。

预先分配一个所需连接长度的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...
预先分配一个所需连接长度的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的调用可能有用,也可能无用。只需将每个子字符串追加到结果中,您可能会得到相同的分配行为。

我将建议使用与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的调用可能有用,也可能无用。通过将每个子字符串追加到结果中,您可能会得到相同的分配行为。

A+=B+C+D;很多临时字符串。A+=B;A+=C;A+=D;运算符+会将C字符串强制为std::string,从而导致如您所说的分配。也许你可以考虑使用一些C字符串API,因为这些是C字符串,如StrCAT或StrnCAT,从.Vivik几乎运算符+为cstring和c字符串重载;其余的都很好。@Vivick或don't。std::string或CString的基准字符串连接,包括代表您的动态内存管理,与您自己滚动并使用strcat和/或strncat之类的工具相比,这些功能被避免了:长度测定。@richardcritten:对其进行了快速测试,没有区别a+=B+C+D;很多临时字符串。A+=B;A+=C;A+=D;运算符+会将C字符串强制为std::string,从而导致如您所说的分配。也许你可以考虑使用一些C字符串API,因为这些是C字符串,如StrCAT或StrnCAT,从.Vivik几乎运算符+为cstring和c字符串重载;其余的都很好。@Vivick或don't。std::string或CString的基准字符串连接,包括代表您的动态内存管理,与您自己滚动并使用strcat和/或strncat之类的工具相比,这些功能都被避免了:长度测定。@Richard Criten:对它做了一个快速测试,没有任何区别。Will将对此进行检查。虽然我认为我必须在遗留代码库中坚持使用CString。。。或者有一种简单的转换方法吗?@DanielG你可以用两个迭代器构造一个rope,你可以从你的CString中获得。我会检查一下。虽然我认为我必须在遗留代码库中坚持使用CString。。。或者有一种简单的转换方法吗?@DanielG你可以用两个迭代器构造一个rope,你可以从你的CString中获得。谢谢。这就是我要找的。但我接受另一个类似的答案,因为我同意这个答案。谢谢。这就是我要找的。但是我接受了另一个类似的答案,因为我将使用这个答案。在使用CString方法时,我完全错过了Preallocate。这肯定好得多。运算符+=不需要调用GetString:result+=前缀就可以工作;结果+=bigString;结果+=后缀;这避免了重新计算字符数或创建临时对象。在使用CString方法时,我完全错过了预分配。这肯定好得多。运算符+=不需要调用GetString:result+=前缀就可以工作;结果+=bigString;结果+=后缀;这样可以避免重新计算字符数或创建临时对象。