将 std::string 转换为 std::wstring 时,C++17 codecvt 抛出“错误转换”
Posted
技术标签:
【中文标题】将 std::string 转换为 std::wstring 时,C++17 codecvt 抛出“错误转换”【英文标题】:C++17 codecvt throw "bad conversion" when convert std::string to std::wstring 【发布时间】:2019-11-04 09:34:24 【问题描述】:我写了一个名为UString
的字符串类,我想要的是可以将std::string
转换为std::wstring
,也可以将std::wstring
转换为std::string
。
我使用的是c++17中的库,所以我写的代码如下。
在 UString.h 中:
public:
UString(std::string s);
UString(std::wstring ws);
private:
std::string str;
std::string WTS(const std::wstring & wstr);
std::wstring STW(const std::string & str);
public:
std::wstring w_str();
const wchar_t* wc_str();
在 UString.cpp 中:
UString::UString(std::string s)
str = s;
UString::UString(std::wstring ws)
str = WTS(ws);
std::string UString::WTS(const std::wstring & wstr)
std::string ret;
try
std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
ret = wcv.to_bytes(wstr);
catch (const std::exception& e)
std::cerr << e.what() << std::endl;
return ret;
std::wstring UString::STW(const std::string & str)
std::wstring ret;
try
std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
ret = wcv.from_bytes(str);
catch (const std::exception & e)
std::cerr << e.what() << std::endl;
return ret;
std::wstring UString::w_str()
return STW(str);
const wchar_t* UString::wc_str()
return STW(str).c_str();
它应该像这样工作:
UString ustr="test"; //the value should be "test"
UString ustr2=L"test2"; //the value should be "test2"
wcout<<ustr.w_str()<<endl; //the value should be "test"
cout<<ustr.wc_str()<<endl; //the value should be "test"
在 linux、GCC 8.0.1 中,该类工作正常,但在 Windows、Visual Studio 2017 中,当我使用 UString::w_str()
或 UString::wc_str()
时,它无法工作并引发“错误转换”错误。
我应该怎么做才能完成这项工作?
【问题讨论】:
看起来你的代码中有 UB,返回一个指向堆栈上某物的指针 值得注意的是,在 Windows 中,wchar_t 代表一个 UTF16 字符,而在所有其他操作系统中,它代表一个 32 位代码点。不幸的是,这使得 wchar_t 在系统之间完全不兼容。我强烈怀疑您需要条件代码来处理 windows 案例。 Can't reproduce.w_str()
call 对我有用,并产生预期的数据。 std::cout << wc_str()
打印存储在指针中的地址,因为您将 wchar_t*
输出到窄流中。如果您改用std::wcout
,程序将表现出未定义的行为。
【参考方案1】:
wc_str()
返回一个悬空指针;调用者对其返回值的任何使用都会表现出未定义的行为,方法是在对象的生命周期结束后访问对象。
STW(str)
生成一个临时文件,然后c_str()
获取一个指向由该临时文件管理的数据的指针。然后临时对象被销毁,数据随之被删除,指针变得悬空。
【讨论】:
可能根本不提供wc_str()
成员。 w_str()
应该足够了。
但是w_str()
函数也不能工作,它会抛出bad_conversion
错误。
正如我在之前的评论中提到的,can't reproduce以上是关于将 std::string 转换为 std::wstring 时,C++17 codecvt 抛出“错误转换”的主要内容,如果未能解决你的问题,请参考以下文章
将 std::__cxx11::string 转换为 std::string
将 std::string 转换为 std::wstring 时,C++17 codecvt 抛出“错误转换”
C++ .NET 将 System::String 转换为 std::string