【问题标题】:Obtaining wrong Value of a given input Key for an unordered map in C++在 C++ 中为无序映射获取给定输入键的错误值
【发布时间】:2020-03-11 07:27:34
【问题描述】:

我正在尝试将对象存储在无序映射中,使用自定义构建哈希函数,下面是代码,

#include <iostream>
#include <unordered_map>
#include <string>

//Class that I want to store in unordered map
class Tree{
public:
    int val;
    std::pair<int,int> location;

    Tree(int val,std::pair<int,int> location){
        this->location = location;
        this->val = val;}
};


//I guess this operator is internally used by the unordered map to compare the Values in the maps. 
//This function returns True only when the val of both the nodes are equal.

bool operator ==(const Tree& node1, const Tree& node2){
    return node1.val == node2.val;}

//Custom build Hash Function for assigning Keys to the Values.
class HashFunction{
public:
    size_t operator()(const Tree& node) const{
        std::hash<int> Hash;
        return Hash(node.val);
    }
};

//Created a class dictionary using the std::unordered_map to store the objects.
class dictionary{
public:
    std::unordered_map<Tree,Tree*,HashFunction> dict;

    void append(Tree node){
        this->dict[node] = &node;}

    Tree* get(Tree node){
        return this->dict[node];}

};


int main(){

    Tree obj1(1,std::make_pair(1,6));
    Tree obj2(2,std::make_pair(2,5));
    Tree obj(2,std::make_pair(3,4));

    dictionary dict;
    dict.append(obj1);
    dict.append(obj2);


    std::cout<<"#################"<<std::endl;  
    std::cout<<dict.get(obj)->location.first<<std::endl;    

}

得到的结果是'3'(如obj.val),而不是'2'(如obj2.val)。

我在main函数中创建了Tree类obj1、obj2和obj三个对象。 obj1 和 obj2 存储在字典中,obj 用于检查字典中匹配的对象。由于哈希函数使用对象的 val 创建键,因此 obj2 和 obj 将具有相同的键,但是当我尝试使用 obj 作为输入访问字典时,字典应该返回 obj2 而不是我得到 obj 这是不在字典中,我不明白为什么会这样。 任何建议,将不胜感激。 在此先感谢:)

【问题讨论】:

  • this-&gt;dict[node] = &amp;node; 将导致未定义的行为,因为您的 unordered_map 将存储指向在函数离开后过期的局部变量的指针。你的意图是什么?
  • 您不必要地复制了很多 Tree 对象,这(至少部分地)导致了这个问题。在适当的时候尝试使用pass by (const) reference

标签: c++ class dictionary pointers unordered-map


【解决方案1】:

dictionary::append 中,您插入一个指向局部变量 (node) 的指针作为值:

this->dict[node] = &node;

一旦函数结束,这个指针将不再有效。

稍后尝试取消引用该指针会导致undefined behavior。这种未定义的行为(在您的情况下)通过访问错误的对象(特别是 dictionary::get 函数的参数)表现出来。情况可能会更糟。

要修复它,您只需将函数更改为:

void append(Tree& node){
    this->dict[node] = &node;}

你仍然需要依赖main 中的对象来保持存在,但至少它应该做你想做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多