wstring的:: c_str()包含垃圾(wstring::c_str() contains g

2019-10-21 02:50发布

我有一个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进行编译。

Answer 1:

const wchar_t *result = decode(src).c_str();

的返回值decode是临时值和调用之后销毁c_str() 从而result点释放的内存。

因此,无论

  • 延伸的返回值的寿命(其分配给一个局部变量,例如)
  • 复制结果


Answer 2:

12.2临时对象[class.temporary]

3当实现引入了具有一个非平凡的构造(12.1,12.8)一类的临时对象时,它必须确保一个构造函数被调用的临时对象。 同样,析构函数应被称为用于与非平凡的析构函数(12.4)的临时。 临时对象被销毁作为评价充分表达(1.9)是(词法)包含了他们所创建点的最后一步。 即使评价抛出异常结束。这是真实的。 值的计算和销毁临时对象的副作用仅与全表达相关,不与任何特定的子表达式。

所以,不要使用一个临时它在你的第一个例子中被毁后,等。



Answer 3:

您的具体问题的答案既可提供了良好的答案被发现。 由于问题的标题是简单地wstring::c_str() contains garbage我要指出的方式来得到的结果是正确的decode功能。

微软增加了许多ATL转换宏和类的宽字符(Unicode)和MBCS(ASCII)之间的转换。 他们可在VS2008。 支持的转换可以在找到MSDN文档 :

ATL 7.0引入了几个新的转换类和宏,提供比现有的宏显著的改善。 新的字符串转换类和宏的名称的形式为:C 2 SourceType中[C] DestinationType [EX]。

[剪断]

SourceType中/ DestinationType

A = ANSI字符串。

W = Unicode字符的字符串。

T =通用字符串(相当于至W _UNICODE被定义时,相当于一个其它)。

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代码页,你也可以留下过CP_ACP是这样的:

std::wstring res = CA2W(src);
const wchar_t *result = res.c_str();

关于与同样的道理也适用于由这些宏返回的类临时对象的问题。 微软甚至文档与先前提供的链接不正确的使用示例这个问题:

// 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);
}


文章来源: wstring::c_str() contains garbage