【问题标题】:C++ specialization of operator[] in unordered_mapunordered_map 中 operator[] 的 C++ 特化
【发布时间】:2014-01-30 15:30:01
【问题描述】:

我一直在使用unordered_map<int, myObject>myObject* 指向无序映射中对象的指针。这已经工作了一段时间,但我最近发现我错误地认为添加到无序映射的 myObject 的内存位置将始终保持不变。

在无序映射中添加和删除元素时,我可以通过使用unordered_map<int, myObject*>newdelete 来解决问题。

由于我有相当多的代码,我不想在代码中修改无序映射的每个地方都添加newdelete,我宁愿尝试重载unordered_map::operator[]unordered_map::erase() 这样newdelete 的使用将透明地发生,我不必更改现有代码。 unordered_map::operator[] 然后可以返回对 myObject 本身的引用而不是指针。

我尝试过继承unordered_map,但我不确定应该如何添加模板参数列表:

using namespace std;

template<class _Kty,
class _Ty,
class _Hasher = hash<_Kty>,
class _Keyeq = equal_to<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >
class  my_unordered_map : public unordered_map<_Umap_traits<_Kty, _Ty,
_Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false> >
{

};

但我收到以下错误:

error C2976: 'std::unordered_map' : too few template arguments
error C2955: 'std::unordered_map' : use of class template requires template argument list

然后我意识到,当使用带有unordered_mapmyObject* 类型时,可以向std 添加一个特化,但我不确定是否甚至可以用特化重载operator[]

感谢您的帮助!

编辑:

我现在创建了一个template &lt;class mapped_type&gt; 类,其中unordered_map&lt;int, mapped_type*&gt; 作为内部结构。 operator[] 包含相当简单:

template <class mapped_type> class MyMap {
public:
    std::unordered_map<int, mapped_type*> internal_map;

    mapped_type& operator[](int&& _Keyval)
    {   // find element matching _Keyval or insert with default mapped
        mapped_type*& ptr = internal_map[_Keyval];
        if (ptr == nullptr) ptr = new mapped_type();
        return *ptr;
    }
}

void erase(const int& _Keyval)
{   // erase and count all that match _Keyval
    mapped_type* ptr = internal_map[_Keyval];
    if (ptr) delete ptr;
    internal_map.erase(_Keyval);
}

void clear()
{   // erase all
    internal_map.clear();
}

现在问题是擦除方法(默认方法包含在std::_Hash 中)。我真的不需要迭代器,所以我想最好的方法可能是首先使用operator[] 方法来查找条目,然后在将其从internal_map 中删除之前使用delete,或者您还有其他想法吗?可能更合适?

编辑:添加了擦除建议。这有道理吧?

【问题讨论】:

  • 使用myObject 的值语义包装器怎么样?类似于unique_ptr&lt;myObject&gt;,但在默认ctor 中自动创建myObject。或者您可以使用std::map,它的insert 函数不会使引用无效。
  • 感谢您的评论,我不知道 std::map 并没有使引用无效。我现在已经更新了我的问题,我将首先尝试以建议的方式解决它。
  • 您正在更改地图中存储的指针的副本。你必须使用类似mapped_type*&amp; ptr = internal_map[_Keyval];
  • 确实如此,谢谢! :)
  • “我最近发现我错误地认为添加到无序映射中的 myObject 的内存位置将始终保持不变。”你是对的,现在又错了:修改unordered_map 的操作可以使迭代器 无效,但不能使指针或对元素的引用无效(擦除元素的明显例外)。元素本身永远不会移动。

标签: c++ operator-overloading template-specialization unordered-map


【解决方案1】:

要从std::unordered_map继承,使用就足够了

template <class T,class V> 
class MyMap : public unordered_map<T, V>

如果您可以使用 std 分配器和散列函数。但请注意,标准容器中没有虚拟析构函数。

无论如何,在我看来,你最终想要做的事情就像你想要一个 intrusive 容器。如果是这样,那么就有this相关的SO问题。

【讨论】:

  • 从标准容器继承并不是一个好主意
  • @n.m.添加了免责声明。
  • 谢谢你的建议,我现在已经更新了我的问题,看来我可以通过这种方式解决问题。
猜你喜欢
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多