【问题标题】:How to handle misses in a C++ HashMap get(key) function?如何处理 C++ HashMap get(key) 函数中的未命中?
【发布时间】:2013-10-14 19:19:51
【问题描述】:

我在 C++ 中实现了一个哈希映射,以便了解更多关于一般关联映射的信息,除了一个症结之外,一切都运行良好——我希望程序员能够创建具有任意参数化的映射(例如 [使用 @987654321 @例如]HashMap<string,string*>HashMap<string,string>HashMap<string*,string>等都是合法的)。

问题在于,在HashMap::get(int key_data) 函数中,如果我支持将对象作为映射值,则在未命中(给定键与任何映射值不匹配的情况下)返回的映射值不能简单地为NULL。我可以让get(...) 函数始终返回一个指向参数化映射值类型的指针,但如果该类型已经是一个指针,我不能使用一元 & 运算符,如果它是一个对象,我必须使用& 运营商。我肯定不想用RTTI,所以问题如下:

如何从我的 HashMap::get() 函数中同时允许对象和指向对象的返回类型,这也是允许未命中所必需的?

请记住,我使用的是 gcc 4.7 并打开了 C++11,因此所有 C++11 功能和注意事项都适用。下面遵循我的HashMap::get() 函数到目前为止使用“始终返回指向任何 value_data 恰好是的指针”范例:

template <class key_data,class value_data> value_data*  
HashMap<key_data,value_data>::get(key_data dk) {

    int key = keyGen(dk);

    int hash_val = HashFunc(key);
    HashNode* entry = _table[hash_val];

    while (entry != 0) {
        if (entry->getCurrentKey() == key) {

            //value_data val = entry->getCurrentValue(); //this temporary will be 
            //gone from the stack quickly and therefore the returned pointer to a 
            //pointer (if value_data is a pointer) will segfault

            return &(entry->getCurrentValue()); //this should be legal and yield 
            //a pointer to a pointer (iff value_data was a pointer), but instead 
            //I get a compiler error claiming 
            //operator & requires an lvalue operand...
        }

        entry = entry->next();

    }

    printf("Your get of int key %i resulted in no hits."
           "The returned pointer to Value is NULL!\n",key);


    return NULL;
}

正如 cmets 所述,return &amp;(entry-&gt;getCurrentValue()); 行引发编译器错误,指出运算符 &amp; 需要左值操作数。我可以通过将value_data 临时放到堆栈上来消除该错误,但是当我实际尝试使用它时会导致段错误,因为返回的指针几乎会立即无效。简单地使用引用来抽象出语法问题也不起作用,因为在这种情况下,无法通过 return NULL 实现未命中(ISO 要求引用与原始指针不同,指向有效的左值)。

如果有人对处理可能“无效”的返回引用有任何建议(例如可以查询其他所有内容继承自其有效性的虚拟对象),我也愿意接受。

【问题讨论】:

  • 为什么不看看标准库是如何解决这个问题的?
  • “我得到一个编译器错误,声称运算符 & 需要一个左值操作数...”我敢打赌 getCurrentValue 按值(或指针)返回?如果是这样,它返回一个纯右值。为了让它编译,让它返回一个引用。 (不过,这并不能解决根本问题。)
  • getCurrentValue() 返回任何 value_data 参数化的值;可以是对象或指针(我不支持引用,因为它们不容易允许上面定义的“未命中”)
  • @CCJ 在您的示例中,getCurrentValue 仅在条目存在时才被调用,对吧?所以它可以返回一个引用。
  • @CCJ 如果您使用 operator[] 并且找不到密钥,则标准库关联容器会通过 default-ctor 创建一个新值。在任何情况下,都会返回一个有效的引用。这允许 my_map[key] = something; 无论元素是否事先存在。您可以使用at 成员函数(或find)进行“边界检查”。

标签: c++ pointers c++11 reference hashmap


【解决方案1】:

解决这个问题的一种可能方法是部分模板专业化。有关如何为指针执行此操作的示例,请参阅this other question

基本上(从那里的答案复制),你需要

template <class I>
class GList<I*>
{
    ...
};

为任何指针类型提供一个特殊版本的列表。

【讨论】:

  • hmm,所以像'template class HashMap{...handle mapped objects here};'和 'template class HashMap{...handle mapped pointer here};'?编译器将如何处理使用 value_data 槽中的指针以 (HashMap) 开头的指针对 HashMap 进行参数化的情况 - 是否足够聪明地将 value_data 的数据类型识别为 std::string 然后检查是否还应用了指针或引用运算符来生成正确的代码来处理对象与指针?
  • 我将对此进行试验并很快回信;谢谢你的建议!
  • 对,稍加按摩和上面的 cmets 的帮助就可以了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 2018-03-13
  • 2017-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多