gpt4 book ai didi

c++ - 这是将 CString 与堆还是堆栈一起使用?我如何将它与堆内存一起使用?

转载 作者:行者123 更新时间:2023-11-30 00:51:29 27 4
gpt4 key购买 nike

我正在使用 VS2012。我宁愿从堆中为 CString 分配内存,因此给出以下代码:

  1. CString csToken 是从还是分配内存?
  2. 我是否需要释放 csToken 正在使用的内存,或者它会在函数终止时自动释放?

    TCHAR *sAllCodes = (TCHAR *) calloc(50000,sizeof(TCHAR));       // Dynamically use Heap memory to hold all pipe-delimited codes
    TCHAR *sCode = (TCHAR *) calloc(128,sizeof(TCHAR)); // Dynamically use Heap memory to hold a single code
    DWORD i = 0;

    LoadAllCodes(&sAllCodes); // Custom function

    CString csToken; // Declare the CString variable
    csToken.Append(sAllCodes); // Assign the string to the Cstring variable
    vector<CString> vAllCodes; // Declare the vector variable
    vAllCodes = Split(csToken,L"|"); // Split the CString into a vector array

    while ( i < (DWORD) vAllCodes.size())
    {
    if (vAllCodes[i].StringLength() > 0) // If there is a string in the vector item
    {
    _stprintf_s(sCode,128,L"%s",vAllCodes[i].GetString()); // Get the vector item and copy it into a string

    // Do work on sCode here...
    }
    i++;
    }

    free(sAllCodes);sAllCodes=NULL;
    free(sCode);sCode=NULL;

最佳答案

你的 csToken变量是 CString 的实例分配在堆栈上,因此您无需执行任何操作即可删除它:它的析构函数将在该变量的范围终止时进行适当的字符串清理。

然而,CString 在内部维护对分配在上的实际字符串的引用。
CString实际上使用了 "COW" 技术和引用计数,所以几个CString实例可以共享相同的字符串,它们可以引用相同的字符串。然而,这些是CString 实现细节

CString 基本用法的“带走”如果你有 CString str你不用关注str清理:它将自动CString 管理析构函数。


此外,我想借此机会对您的代码做一些注释,以改进它的精神。

使用 std::vector

您在发布的代码顶部有这些分配:

TCHAR *sAllCodes = (TCHAR *) calloc(50000,sizeof(TCHAR));
TCHAR *sCode = (TCHAR *) calloc(128,sizeof(TCHAR));

然后你在底部有相应的免费电话:

free(sAllCodes);sAllCodes=NULL;
free(sCode);sCode=NULL;

但是请注意,此代码 异常安全:事实上,如果calloc() 之间有任何代码和 free()调用恰好抛出 C++ 异常,在堆上分配的内存为 sAllCodessCode不会被释放。

更现代更实用的C++风格中,您可以使用 std::vector 而不是 calloc()在堆上分配内存,并自动释放它,感谢std::vector析构函数(就像 CString !)。

只需替换 calloc()调用:

std::vector<TCHAR> allCodes(50000);
std::vector<TCHAR> code(128);

然后删除free()电话! :)
除了更简单和更短之外,您的代码也变得异常安全;事实上,如果抛出 C++ 异常,vector 自动调用析构函数,并释放分配的内存。

如果你想访问vector数据,你可以使用它的data()成员函数。

如果要将初始 vector 内容设置为全0,可以使用vector v(count, 0)构造函数重载。

使用 C++ 风格的转换

在你的代码中你有一个 C 风格的 (DWORD) throw 。 C 风格的转换不好;考虑改用C++ 风格的转换。在您的情况下,您可能需要 static_cast<DWORD>(...) .

使用 CString::IsEmpty()提高可读性

你的代码中有一个 if 是这样的:

if (vAllCodes[i].StringLength() > 0)

CString提供方便IsEmpty()方法,更具可读性:

if (! vAllCodes[i].IsEmpty()) 
....

关于 _stprintf_s() 的注释和“魔数(Magic Number)”

您使用 _stprintf_s()像这样:

_stprintf_s(sCode,128,L"%s",vAllCodes[i].GetString()); 

但请注意,如果您使用 TCHAR模型,为了连贯你应该使用 _T("%s") 在格式说明符中。
如果您只想使用 Unicode 字符串和 L"%s" (我建议),然后使用相应的 Unicode-only swprintf_s() ,并去掉 TCHAR只需使用 wchar_t 代替。

另请注意,您可能希望使用 sCode.size() 而不是使用“魔数(Magic Number)”128 (假设 sCode 成为 std::vector 的实例,正如我上面所建议的)。所以,如果你改变 vector 的大小,你不必更新“魔数(Magic Number)”128(有了这些魔数(Magic Number),基本上会有错误等待发生:)
更新后的代码可能类似于:

swprintf_s(code.data(), code.size(), L"%s", vAllCodes[i].GetString()); 

关于c++ - 这是将 CString 与堆还是堆栈一起使用?我如何将它与堆内存一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21702473/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com