我很好奇下面的代码是否正确?我在较旧版本的 VS 2008 上运行它,用于仅 Windows 的 C++ 项目。
我的目标是在 std::string 中预分配内存,以将其传递到 WinAPI 中,并了解所需的字符大小:
//'hWnd' = window handle
int nLn = GetWindowTextLength(hWnd);
//Text variable to collect text in
std::wstring str;
str.reserve(nLn);
GetWindowText(hWnd, (LPTSTR)str.data(), nLn);
我担心的是 str.data()
返回 const wchar_t *
和 GetWindowText()
请求 LPTSTR
>,这不是一个 const
缓冲区。那里可以进行类型转换吗?
最佳答案
我不能代表 VS2008,但大多数 C++11 之前版本都遵循 &str[0] + i == str.data() + i
的 C++11 规则,所以&str[0]
有效并且不需要任何强制转换1,这是比破坏类型系统和标准更安全的途径。请小心,因为您不允许覆盖字符串后面的空终止符,即使使用另一个空终止符也是如此。如果您无法在 VS2008 中保证这一点,那么 std::vector<wchar_t>
将是首选解决方案。
但是,您还有另一个问题。 reserve
并不能阻止访问 str
的未定义行为出界。界限基于 size()
,不是capacity()
。您需要更改reserve
至resize
.
即便如此,你还有另一个问题。 GetWindowTextLength
不包括空终止符。您必须使用nLn + 1
在该调用后面的代码中。
进行更改后,这将适用于任何符合 C++11 的实现,包括一些 C++11 之前的实现,并忽略错误检查:
int nLnWithNul = GetWindowTextLength(hWnd);
std::wstring str(nLnWithNul, '\0'); // bit of a shorthand for the resize call
int nCopiedLn = GetWindowText(hWnd, &str[0], nLnWithNul);
str.resize(nCopiedLn);
最后resize
调用处理短于 nLnWithNul
的复制标题。例如,如果标题从 GetWindowTextLength
开始缩小被称为。调整大小后,字符串将仅包含复制的文本,后面不包含任何 NUL 字符。
1:参见my previous question的答案.
关于c++ - 预分配 std::string 以传递到 WinAPI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34302563/