.c_str()奇怪吗?数据变化没有押韵或原因?

时间:2009-12-07 17:36:19

标签: c++ string wchar-t wstring c-str

我有这个简单的功能:

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    std::wstring originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

在该函数的第二行,我有正确的wchar_t *。但是,当我返回时,数据切换到垃圾数据。两者之间没有任何功能。是什么给了什么?!

5 个答案:

答案 0 :(得分:11)

originalString在堆栈上分配。 .c_str()方法只返回指向wstring对象的某个连续内部内存的指针。当函数返回时,originalString超出范围并被销毁,因此返回的指针值指向已删除的内存。

如果你需要这样做,你应该将数据副本复制到你用new或malloc()分配的内存中,然后调用者必须删除/ free()那个内存。

答案 1 :(得分:5)

您正在返回指向临时的指针。当originalString超出范围时,指针指向的数据将被删除。

答案 2 :(得分:3)

std::wstring originalString;GetWCharTStar函数正文中的局部变量。

一旦你离开GetWCharTStar()函数的范围,这个局部变量就会被破坏,你返回的指针也不再有效。

以下代码可能最终有效:

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    const std::wstring& originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

如果StringManager::GetString()返回引用:

const std::wstring& StringManager::GetString(int stringId);

但是,这仍然存在风险,因为它假定您的StringManager类管理的字符串永远不会重新定位在内存中。例如,如果StringManager是在std::vector的帮助下实现的,那么只要向量需要扩展,其先前的内容就会被复制到更大的内存块中的其他位置,并最终保留对一个不再存在的对象。

换句话说,avoid returning handles to internal data

答案 3 :(得分:1)

除了一个小细节之外,之前的答案大多是正确的。您没有返回指向已销毁对象的指针,而是由被销毁对象返回指针拥有。当该对象被销毁时,指针所指向的对象也被销毁。

答案 4 :(得分:0)

这是常见问题解答。在实际使用之前,您将返回一个指向已释放对象的指针(originalString对象)。