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] 就

这段代码让我烦恼的是结果的双重拷贝

  • 通过API转换为
    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()访问的字符数组是未定义的行为。”我知道这可能没问题,但这不是标准的一部分。