Init std::具有单个副本的字符串 我在Win32上有C++的代码。它只是一些Win32 API上的C++扭曲,返回了 char */COD>: wstring expandEnvironmentVariables(const wstring & str) { DWORD neededSize = ExpandEnvironmentStrings(str.c_str(), nullptr, 0); vector<WCHAR> expandedStr(neededSize); if (0 == ExpandEnvironmentStrings(str.c_str(), expandedStr.data(), static_cast<DWORD>(expandedStr.size()))) { return wstring(str); } return wstring(expandedStr.data()); } wstring expandEnvironmentVariables(const wstring&str) { DWORD neededSize=ExpandEnvironmentStrings(str.c_str(),nullptr,0); 向量扩展str(neededSize); 如果(0==ExpandEnvironmentString(str.c_str(),expandedStr.data(),static_cast(expandedStr.size())){ 返回wstring(str); } 返回wstring(expandedStr.data()); }
这段代码让我烦恼的是结果的双重拷贝Init std::具有单个副本的字符串 我在Win32上有C++的代码。它只是一些Win32 API上的C++扭曲,返回了 char */COD>: wstring expandEnvironmentVariables(const wstring & str) { DWORD neededSize = ExpandEnvironmentStrings(str.c_str(), nullptr, 0); vector<WCHAR> expandedStr(neededSize); if (0 == ExpandEnvironmentStrings(str.c_str(), expandedStr.data(), static_cast<DWORD>(expandedStr.size()))) { return wstring(str); } return wstring(expandedStr.data()); } wstring expandEnvironmentVariables(const wstring&str) { DWORD neededSize=ExpandEnvironmentStrings(str.c_str(),nullptr,0); 向量扩展str(neededSize); 如果(0==ExpandEnvironmentString(str.c_str(),expandedStr.data(),static_cast(expandedStr.size())){ 返回wstring(str); } 返回wstring(expandedStr.data()); },c++,c++11,stdstring,C++,C++11,Stdstring,这段代码让我烦恼的是结果的双重拷贝 通过API转换为WCHARs的向量 从向量到std::wstring 有没有一种方法可以实现这段代码,只需要一个副本,而不需要对函数的签名进行重大更改。 这是一个具体的例子,但是我更感兴趣的是使用“代码> STD::WString /Cudith:St::String ,因为这个模式在代码中的很多地方都显示了自己。 < P>关于C++方面,您可以直接使用 WString 直接作为结果变量。 要获取指向非零大小的wstring缓冲区的指针,只需使用&s[0] 就
WCHAR
s的向量std::wstring
这是一个具体的例子,但是我更感兴趣的是使用“代码> STD::WString /Cudith:St::String ,因为这个模式在代码中的很多地方都显示了自己。 < P>关于C++方面,您可以直接使用<代码> WString 直接作为结果变量。 要获取指向非零大小的
wstring
缓冲区的指针,只需使用&s[0]
就像std::vector
,std::basic_string
有保证的连续缓冲区
对于返回,它可能会得到返回值优化(RVO),如果不是,它将被移动
免责声明:我还没有检查API函数的文档。我不知道这段代码是正确的还是有意义的。我只是假设
wstring expandEnvironmentVariables(const wstring & str)
{
wstring expandedStr;
DWORD neededSize = ExpandEnvironmentStrings(str.c_str(),
nullptr, 0);
if (neededSize)
{
expandedStr.resize(neededSize);
if (0 == ExpandEnvironmentStrings(str.c_str(),
&expandedStr[0],
neededSize))
{
// pathological case requires a copy
expandedStr = str;
}
}
// RVO here
return expandedStr;
}
编辑:
在反射中,因为我们使用C++,让我们去整个HOG,并用一个信息嵌套异常链:正确地错误检测和报告错误:
DWORD check_not_zero(DWORD retval, const char* context)
{
if(!retval)
throw std::system_error(GetLastError(),
std::system_category(),
context);
return retval;
}
std::wstring expandEnvironmentVariables(const std::wstring & str)
try
{
DWORD neededSize = check_not_zero(ExpandEnvironmentStrings(str.c_str(),
nullptr,
0),
"ExpandEnvironmentStrings1");
std::wstring expandedStr(neededSize, 0);
check_not_zero(ExpandEnvironmentStrings(str.c_str(),
&expandedStr[0],
neededSize),
"ExpandEnvironmentStrings2");
// RVO here
return expandedStr;
}
catch(...)
{
std::throw_with_nested(std::runtime_error("expandEnvironmentVariables() failed"));
}
@安吉:不客气。我也很确定,直到我发现遗漏。这很奇怪。我通常更喜欢前面的
而不是&s[0]
。它甚至适用于列表
这样的容器。但是,为什么您需要指向列表
中第一个节点的指针呢?在通用代码中的某个地方,您可能需要它,可能是因为您没有正常的开始/结束范围。请谨慎地检查大小是否为0。表达式&s[0]
对于该大小是UB。@Cheers和Hth.-Alf重新考虑了错误处理。在我看来,最好将操作系统错误转换为系统错误。通过适当地定义函数fail
,您可以将其写成ExpandEnvironmentStrings(…)|fail(“消息”)
。它在C++中没有那么多,但是在脚本语言中是习惯用法。我喜欢,我同意。这实际上是我在自己的项目中所做的。根据cppreference.com的说法,如果你用关键字“或”代替“| |”,效果会更好。“写入通过c_str()访问的字符数组是未定义的行为。”我知道这可能没问题,但这不是标准的一部分。