我很好奇以下代码是否正确?对于仅支持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
缓冲区。那种类型演员会好吗?
答案 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