在 C++ 中将 getter 用于 unordered_map 会创建大小为 8 的无效读取

Using getter for an unordered_map in c++ creates an invalid read of size 8

我正在尝试对字段 std::unordered_map<std::string, User *> userMap 使用 getter 以在其中查找用户。

我做得太累了:

   std::unordered_map<std::string, User *>::const_iterator found = getUserMap().find(userName);

但 valgrind 检测到大小为 8 的无效读取。 但是,当我这样做时:

std::unordered_map<std::string, User *> tmpUserMap = getUserMap();
    std::unordered_map<std::string, User *>::const_iterator found = tmpUserMap.find(userName);

无效读取消失了。

getter 是标准 getter:

std::unordered_map<std::string, User *> Session::getUserMap() const{
    return userMap;
}

如果需要,我可以提供 valgrind 数据,我在 clion 编辑器上使用 c++11。

getUserMap returns userMap 副本 。这意味着您获得的迭代器只能与所述副本一起使用。

因此,当您存储副本然后将迭代器与它一起使用时,一切正常。

当您多次调用 getUserMap 时,您会获得地图的 不同 和临时副本。您不能使用从第一个副本(现在无效,因为它的映射是临时的)获得的迭代器来访问第二个副本。当您尝试时会出现未定义的行为,这就是您看到令人困惑的错误的原因。

这是按值返回的本质,它总是returns一个新对象而不是原始对象。如果你想直接读取 userMap,那么考虑返回一个 const 引用来代替它:

std::unordered_map<std::string, User *> const& Session::getUserMap() const{
    return userMap;
}

执行此操作时:

std::unordered_map<std::string, User *>::const_iterator found = getUserMap().find(userName);

您正在使用临时对象的方法find()。因此,您得到的迭代器在语句执行后无效(参见the lifetime of temporary objects)。

在其他代码中,tmpUserMap实际上不是一个临时对象,迭代器仍然可用,因为它的源还没有被销毁。

为什么在第一个片段集中得到一个临时对象?因为 getUserMap() returns 按值会触发创建 userMap.

的副本