为啥我应该使用 CString 的 GetBuffer 成员而不是 SetAt?

Posted

技术标签:

【中文标题】为啥我应该使用 CString 的 GetBuffer 成员而不是 SetAt?【英文标题】:Why should I use GetBuffer member of CString instead of SetAt?为什么我应该使用 CString 的 GetBuffer 成员而不是 SetAt? 【发布时间】:2016-11-16 00:04:52 【问题描述】:

我目前正在研究 MFC 库,我想知道为什么我应该使用 GetBuffer 成员,它返回指向 CString 对象缓冲区的指针,而不是其他允许读取和更改该对象中字符的成员函数? 例如为什么我应该这样做(代码更改 CString 对象的第一个字符):

CString aString(_T("String")); //new CString object
LPTSTR p = aString.GetBuffer(); //create new pointer to aString buffer
_tcsncpy(p, LPCTSTR(_T("a")), 1); //set first character to 'a'
aString.ReleaseBuffer(); //free allocated memory

代替:

CString aStr(_T("String")); //new CString object
aStr.SetAt(0, _T('a')); //set character at 0 position to 'a'

我想有一个更合适的应用程序使用 GetBuffer() 成员,但我不知道它可以是什么......这个函数需要 ReleaseBuffer() 来释放内存,我在 ReleaseBuffer 时可能会导致内存泄漏() 不被调用。使用它有什么好处吗?

【问题讨论】:

【参考方案1】:

在上面的例子中,最好使用SetAt 方法。

在某些情况下,您需要GetBuffer 直接访问缓冲区,主要是在与 WinAPI 函数一起使用时。例如,要将::GetWindowText 与 WinAPI 代码一起使用,您需要按如下方式分配缓冲区:

int len = ::GetWindowTextLength(m_hWnd) + 1;
char *buf = new char[len];
::GetWindowText(m_hWnd, buf, len);
...
delete[] buf;

在 MFC 中使用CWnd::GetWindowText(CString&) 可以完成相同的操作。但是 MFC 必须通过GetBuffer 使用相同的基本 WinAPI 函数。 MFC对CWnd::GetWindowText的实现大致如下:

void CWnd::GetWindowText(CString &str)

    int nLen = ::GetWindowTextLength(m_hWnd);
    ::GetWindowText(m_hWnd, str.GetBufferSetLength(nLen), nLen+1);
    str.ReleaseBuffer();

【讨论】:

【参考方案2】:

除非您别无选择,否则不要使用GetBuffer。正是因为(1)你已经知道的原因,它必须跟着ReleaseBuffer,你可能会忘记这样做,导致资源泄漏。并且 (2) 您可能会无意中对底层数据进行更改,从而使其以某种方式不一致。通常情况下,GetString、SetString、GetAt 和 SetAt 函数可以满足您的需要,而且没有缺点。更喜欢他们。

【讨论】:

以上是关于为啥我应该使用 CString 的 GetBuffer 成员而不是 SetAt?的主要内容,如果未能解决你的问题,请参考以下文章

刚开始学C++,想请教高手们一下,将CString类型字符串转换为unsigned char型字符数组的转化方式

为啥我需要这个 CString 类型转换?

为啥我不能在 MFC 中比较 CString

为啥使用 DT_MODIFYSTRING 选项将副本传递给 DrawText 函数时,原始 CString 会被覆盖?

为啥CString变量无法赋值?

为啥我应该使用单独的测试目标来运行 XCTests,我应该怎么做?