我有一个std::wstring decode(const char *s)
功能。
我这样用:
const char *src = "some string";
const wchar_t *result = decode(src).c_str();
我总是在result[0]
中出现垃圾,有时也在result[1]
。
当我以另一种方式使用它时,我不会得到垃圾:
std::wstring res = decode(src);
const wchar_t *result = res.c_str();
我的decode
功能定义如下,它完成了它的工作。唯一的问题是调用代码(上图)。
std::wstring decode(const char *s, UINT cp=CP_ACP)
{
if(s == NULL)
return std::wstring();
int length = ::MultiByteToWideChar(cp, 0, s, -1, NULL, 0 );
wchar_t *buf = new wchar_t[length];
::MultiByteToWideChar(cp, 0, s, -1, buf, length);
std::wstring r(buf);
delete[] buf;
return r;
}
我使用Visual C ++ 2008 SP1进行编译。
答案 0 :(得分:7)
const wchar_t *result = decode(src).c_str();
decode
的返回值是一个临时值,在调用c_str()
后会被销毁。因此result
指向释放的记忆。
所以要么
答案 1 :(得分:5)
12.2临时对象
[class.temporary]
3当实现引入具有非平凡构造函数(12.1,12.8)的类的临时对象时,它应确保为临时对象调用构造函数。类似地,应该使用非平凡的析构函数(12.4)调用析构函数。 临时对象在评估全表达式(1.9)的最后一步时被破坏,该表达式(词法上)包含创建它们的点。即使该评估以抛出异常结束,也是如此。销毁临时对象的值计算和副作用仅与完整表达式相关联,而不与任何特定子表达式相关联。
所以,不要在它被破坏后使用临时,就像在你的第一个例子中一样。
答案 2 :(得分:1)
您提供的好答案都可以找到您具体问题的答案。由于问题标题只是wstring::c_str() contains garbage
,我将指出一种方法来获得正确的结果没有 decode
函数。
Microsoft添加了许多 ATL 转换宏和类,以便在宽字符(Unicode)和MBCS(Ascii)之间进行转换。它们可在VS2008上使用。支持的转化可在MSDN Documentation:
中找到ATL 7.0引入了几个新的转换类和宏,相对于现有的宏提供了重大改进。新字符串转换类和宏的名称采用以下形式: <强> C 强> SourceType中的 2 强> [C] DestinationType [EX]。
[剪断]
SourceType / DestinationType
A = ANSI字符串。
W = Unicode字符串。
T =通用字符串(定义_UNICODE时等效于W,否则等效于A)。
OLE = OLE字符串(相当于W)。
[EX]
是可选的,如果您不想指定与宏一起使用的默认内部缓冲区的大小,则经常使用它。
在你的情况下,转换宏CA2W
(将Ascii转换为Widechar)应该做你想要的。您只需#include <atlbase.h>
即可使用它们。这些宏需要2个参数 - 要转换的字符串和代码页(如果未指定,则默认为CP_ACP)
在你的情况下,你有:
std::wstring res = decode(src);
const wchar_t *result = res.c_str();
使用ATL转换宏可以这样做:
std::wstring res = CA2W(src, CP_ACP);
const wchar_t *result = res.c_str();
由于宏默认为Ansi Code Page,您也可以像这样取消CP_ACP:
std::wstring res = CA2W(src);
const wchar_t *result = res.c_str();
关于临时对象的问题,同样的事情适用于这些宏返回的类。 Microsoft甚至在前面提供的链接中使用了错误的用法示例来记录此问题:
// Example 3
// Incorrect use of conversion macros.
void ExampleFunction3(LPCWSTR pszW)
{
// Create a temporary instance of CW2A,
// save a pointer to it and then delete
// the temportary instance.
LPCSTR pszA = CW2A(pszW);
// The pszA in the following line is an invalid pointer,
// as the instance of CW2A has gone out of scope.
ExampleFunctionA(pszA);
}