【问题标题】:Elements inserted into map cleared after function executes函数执行后,插入地图的元素被清除
【发布时间】:2018-04-12 15:47:06
【问题描述】:

我正在尝试创建一个函数,它将名为 Project 的自定义对象向量的元素转换为以“键”作为这些项目的 ID、存储在成员变量中的映射以及项目本身的映射值.为此,我有一个简单的函数,它传递一个指向向量的指针作为参数,循环通过(取消引用的)向量,并为每个元素检索其 ID 并使用 [ ] 映射运算符分配对,如图所示。地图声明如下:

map<int, Project*> unassigned_projects;

函数如下:

void Solution::setup_project_map(vector<Project>* project_list) {
    for (int i = 0; i != size(*project_list); ++i) {
        int project_id = (*project_list)[i].get_project_id();
        this->unassigned_projects[project_id] = &((*project_list)[i]);
    }
}

我遇到的问题是它在函数内部进行了正确的分配(您可以在调试器 in this picture 中看到结果如何),但是一旦函数退出存储在对象中的所有数据重置为默认值,如 in this picture 所示。

我的理解是,如果我将实际的向量对象传递给函数,这将是有意义的,因为一旦函数完成,临时对象将被删除,因此指向该对象元素的任何指针也将变为未定义,或者如果我使用的是 range-for 循环并且它正在创建元素的副本。但是,由于我通过引用传递向量并在每个阶段直接取消引用它,因此函数内部和外部的值应该保持不变。我过去曾遇到过没有正确使用传递引用的问题,所以我怀疑这是我在某种程度上出错的地方。

提前致谢!

【问题讨论】:

  • 混合vector&lt;Project&gt; 和map&lt;int, Project*&gt; 将是一个问题。有什么理由不使用map&lt;int, Project&gt;?
  • 好吧,我试图避免创建项目的副本,但如果这样可以解决问题,这可能不是什么大问题。为什么这样做可能会导致问题?
  • 好吧,如果向量超出范围,那么映射中的所有指针都指向被销毁的对象。
  • 这是有道理的。不过,原始向量当然不应该超出范围(请参阅下面帖子的评论)。
  • 看不到的代码我们帮不上忙,只能猜测,发个mvce

标签: c++ pointers dictionary vector


【解决方案1】:

您正在映射中存储指向 Projects 的指针,但如果 vector 死掉(由于最终超出范围,我们无法从您的代码中判断发生的位置),那么每个 @987654324 也是如此@ 在里面。地图中的所有指针现在都指向不再存在的Projects。如果您尝试从死项目中读取,您会得到未定义的行为,并且调试器可能会或可能不会显示垃圾或错误。

您应该弄清楚谁管理您的 Project 对象的生命周期,以及是否需要复制它们以使它们保持活力。现在vector 总是管理生命周期,如果地图的寿命比矢量长,这是一个问题。您可以将所有权共享给Projects,您可以在函数中转让所有权,或者您可以在函数中创建副本以分隔生命周期。前两个选项最好分别使用std::shared_ptr 和std::unique_ptr 实现。

【讨论】:

  • 不仅是 map 的寿命超过了向量,而且如果向量被某种方式修改,它的迭代器无效
  • 该向量包含在一个算法类中,该类包含一组数据,其中存储了 project_list 以及正在执行此函数的对象,因此在主实例之后不应删除它删除算法。它当然不应该在这个函数执行完成后立即删除,我可以在调试器中看到,一旦函数退出,数据就会被清除。
  • @whelkstrider 如果您想要更好的答案,您需要提供Minimal, Complete, and Verifiable example。您提供的代码没有明显问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多