【问题标题】:unable to modify a vector of const wchar *无法修改 const wchar 的向量 *
【发布时间】:2021-09-23 04:02:38
【问题描述】:

我有一个函数可以将字符串列表转换为 const wchar_t * 的向量。

void convertListtoVector(std::vector<const wchar_t *>& messageInserts)
{
    std::list<std::wstring> Inserts;
    Inserts.push_back(L"str1");
    Inserts.push_back(L"str2");
    Inserts.push_back(L"str3");

    std::list<std::wstring>::iterator itr;
    
    for (itr = Inserts.begin(); itr != Inserts.end(); itr++) {
        messageInserts.push_back((*itr).c_str());
    
    }
}

我这样称呼它:

std::vector<const wchar_t *> msg;
convertListtoVector(msg);

但在函数执行后,我有一个包含 3 个空字符串的向量。当我调试我的代码时,我注意到在函数内部,向量正在用字符串更新,但在函数返回后,我看到大小从 0 变为 3,但所有字符串都是空的“”。我想要带有字符串的向量。请让我知道我哪里出错了。 提前致谢。

【问题讨论】:

    标签: c++ windows visual-c++ msdn


    【解决方案1】:

    在使用地址清理程序构建程序时,我们检测到内存错误:AddressSanitizer: heap-use-after-free

    通常在现代 c++ 中,我们不建议使用原始指针:我们更喜欢使用容器。

    你已经存储了本地std::list拥有的字符串地址,函数返回后,这些地址不可访问(打印时你得到一个空字符串,但实际上它可能会崩溃),修复它我们可以有3个选择:

    1. 制作副本
    void convertListtoVector(std::vector<std::wstring>& messageInserts)
    {
        std::list<std::wstring> Inserts;
        Inserts.push_back(L"str1");
        Inserts.push_back(L"str2");
        Inserts.push_back(L"str3");
    
        std::list<std::wstring>::iterator itr;
        
        for (itr = Inserts.begin(); itr != Inserts.end(); itr++) {
            messageInserts.push_back(*itr);
        
        }
    }
    

    或使用 STL 算法

    void convertListtoVector(std::vector<std::wstring>& messageInserts)
    {
        std::list<std::wstring> Inserts;
        Inserts.push_back(L"str1");
        Inserts.push_back(L"str2");
        Inserts.push_back(L"str3");
        messageInserts.insert(messageInserts.end(), Inserts.begin(), Inserts.end());
    }
    
    1. 从本地容器移动,因为不再需要本地列表,对于大字符串,移动它们将获得性能提升
    void convertListtoVector(std::vector<std::wstring>& messageInserts)
    {
        std::list<std::wstring> Inserts;
        Inserts.push_back(L"str1");
        Inserts.push_back(L"str2");
        Inserts.push_back(L"str3");
        
        for (itr = Inserts.begin(); itr != Inserts.end(); itr++) {
            messageInserts.push_back(std::move(*itr));
        }
    }
    

    或使用 STL 算法

    void convertListtoVector(std::vector<std::wstring>& messageInserts)
    {
        std::list<std::wstring> Inserts;
        Inserts.push_back(L"str1");
        Inserts.push_back(L"str2");
        Inserts.push_back(L"str3");
        messageInserts.insert(messageInserts.end(), std::make_move_iterator(Inserts.begin()), std::make_move_iterator(Inserts.end()));
    }
    
    1. 将本地list 设为静态,但这可能容易出错:
    void convertListtoVector(std::vector<const wchar_t*>& messageInserts)
    {
        static std::list<std::wstring> Inserts;
        Inserts.push_back(L"str1");
        Inserts.push_back(L"str2");
        Inserts.push_back(L"str3");
    
        std::list<std::wstring>::iterator itr; 
        for (itr = Inserts.begin(); itr != Inserts.end(); itr++) {
            messageInserts.push_back(itr->c_str());
        }
    }
    

    【讨论】:

      【解决方案2】:

      您的向量存储一个指向字符串的指针,该字符串的生命周期由std::list 管理。当列表作为局部变量被删除时,所有托管字符串也被删除,并且你在向量中留下了悬空指针。

      您必须对列表的字符串内容进行深层复制:

      void convertListtoVector(std::vector<const wchar_t *>& messageInserts)
      {
          std::list<std::wstring> Inserts;
          Inserts.push_back(L"str1");
          Inserts.push_back(L"str2");
          Inserts.push_back(L"str3");
      
          std::list<std::wstring>::iterator itr;
          
          for (itr = Inserts.begin(); itr != Inserts.end(); itr++) {
              wchar_t *cloneStr = new wchar_t[wcslen(itr->c_str())+1];
              wcscpy(cloneStr,itr->c_str());
              messageInserts.push_back(cloneStr);
          }
      }
      
      int main(){
          std::vector<const wchar_t *> msg;
          convertListtoVector(msg);
          for (const wchar_t* str : msg) {
              std::wcout << str << std::endl;
              delete[] str;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-03-18
        • 2012-01-28
        • 2015-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-22
        • 2012-07-14
        • 2011-04-09
        相关资源
        最近更新 更多