预分配std :: string以传入WinAPI

时间:2015-12-16 01:31:57

标签: c++ windows winapi std stdstring

我很好奇以下代码是否正确?对于仅支持Windows的C ++项目,我在一个较旧版本的VS 2008上运行它。

我的目标是在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缓冲区。那种类型演员会好吗?

2 个答案:

答案 0 :(得分:3)

我无法代表VS2008,但大多数前C ++ 11都遵循&str[0] + i == str.data() + i的C ++ 11规则,因此&str[0]有效,并且不需要任何casts 1 ,这比颠覆类型系统和标准更安全。请注意,因为您不允许在字符串后覆盖空终止符,即使使用另一个空终止符也是如此。如果您无法为VS2008保证这一点,那么std::vector<wchar_t>将是首选解决方案。

但是,您还有另一个问题。 reserve并不会阻止它访问str超出界限的未定义行为。界限基于size(),而不是capacity()。您需要将reserve更改为resize

即使这样,你还有另外一个问题。 GetWindowTextLength不包含空终止符。您必须在该通话后的代码中使用nLn + 1

通过所做的更改,这将适用于任何符合C ++ 11的实现,包括一些pre-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的答案。

答案 1 :(得分:1)

不,你不能按照C ++标准这样做。但是,如果您使用std::vector<wchar_t>代替std::wstring

,则可以执行此操作
int nLn = GetWindowTextLength(hWnd);
std::vector<TCHAR> str(nLn); // size, not reserve()
int size = GetWindowText(hWnd, str.data(), nLn);
str.resize(size); // will make empty in case of error

另请参阅:writing directly to std::string internal buffers