You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何像L""一样将string转为const wchar_t*?解决wstring转指针疑问

问题:将std::string转为wchar_t*的替代方案(不使用c_str())

问题背景

尝试用L""语法处理变量x时,编译器会将其展开为Lx,触发未定义错误,因此自定义了widen函数将std::string转为std::wstring,再尝试转为wchar_t*。

第一版代码及问题

#include <locale>
#include <iostream>
#include <string>
#include <sstream>
using namespace std ;

wstring widen( const string& str )
{
    wostringstream wstm ;
    const ctype<wchar_t>& ctfacet = use_facet<ctype<wchar_t>>(wstm.getloc()) ;
    for( size_t i=0 ; i<str.size() ; ++i ) 
              wstm << ctfacet.widen( str[i] ) ;
    return wstm.str() ;
}

int main()
{
    const char* cstr = "sandbox.exe" ;
    const wchar_t* wcstr = widen(cstr).c_str() ;
    wcout << wcstr << L'\n' ;
  
}

这段代码存在悬垂指针问题:widen(cstr)返回的临时std::wstring在语句结束后立即销毁,wcstr指向的内存已被释放,后续访问属于未定义行为。此外,返回的指针地址与L"sandbox.exe"的地址不同——这是正常现象,因为字符串字面量存储在只读数据段,而std::wstring的缓冲区在堆/栈内存中,存储位置天然不同。

第二版代码及观察

#include <locale>
#include <iostream>
#include <string>
#include <sstream>
using namespace std ;
 
wstring widen( const string& str )
{
    wostringstream wstm ;
    const ctype<wchar_t>& ctfacet = use_facet<ctype<wchar_t>>(wstm.getloc()) ;
    for( size_t i=0 ; i<str.size() ; ++i ) 
              wstm << ctfacet.widen( str[i] ) ;
    return wstm.str() ;
}
 
int main()
{
    const char* cstr = "sandbox.exe" ;
    const std::wstring widestring = widen(cstr);
    const wchar_t* wcstr = widestring.c_str();
    wcout << wcstr << L'\n' ;
 
}

此版本中widestring的内容与L"sandbox.exe"完全一致,但c_str()返回的指针地址仍与字面量不同。核心疑问:如何不使用c_str()将std::wstring转为wchar_t*?


解决方案

1. 使用data()或&str[0](C++11及以后)

C++11标准后,std::wstring::data()与c_str()等价,返回指向内部缓冲区的指针,且缓冲区以\0结尾。此外,也可以用&widestring[0]获取指针(注意:空字符串时&widestring[0]是未定义行为,data()则安全返回指向\0的指针)。

示例:

const std::wstring widestring = widen(cstr);
const wchar_t* wcstr1 = widestring.data();
const wchar_t* wcstr2 = &widestring[0]; // 仅当widestring非空时安全

注意:这两个方法返回的指针生命周期与widestring绑定,若widestring被销毁、修改或扩容,指针会失效。

2. 手动分配内存复制内容(需管理内存)

如果需要一个独立于std::wstring生命周期的wchar_t*,可以手动分配内存并复制内容:

const std::wstring widestring = widen(cstr);
wchar_t* wcstr = new wchar_t[widestring.size() + 1];
wcscpy(wcstr, widestring.c_str());

// 使用wcstr...

// 必须手动释放内存,避免泄漏
delete[] wcstr;

此方法需要手动管理内存,容易出错,仅在特殊场景下使用。

关键说明

std::wstring的内部缓冲区地址与字符串字面量地址不同是完全正常的,二者存储位置不同(字面量在只读数据段,wstring缓冲区在动态内存),无需纠结地址差异,只要内容正确即可。


内容的提问来源于stack exchange,提问作者kaan kaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:15:29