【问题标题】:Custom STL Containers自定义 STL 容器
【发布时间】:2009-03-19 16:10:50
【问题描述】:

我编写的代码允许按照输入的顺序遍历映射数据。

我编写了几次的解决方案是:

给定键类型 K 和数据类型 D, 标准::地图 标准::向量

如果想随机查找数据条目,请使用map.find(K)。如果想按入口顺序遍历地图,请使用std::vector::iterator (begin(), end()]

这很好,但作为一个练习,我想把这个'OrderedMap' 写成一个符合 STL 的容器。我也有(精简到这个讨论):

template <typename K, typename D>
class OrderedMapValue
{
private:
    K first_ref;
    std::map<K,size_t>& m;
    std::vector<D>& v;
public:
    const K& first
    D& second
    assignment operator=(const D& data) 
    {
        std::map<K,size_t>::const_iterator iter = m.find(first_ref);
        v[iter.second] = data;  // error checking of iter stripped
    }
};

进一步假设

template <typename K, typename D>
class OrderedMap
{
public:
     typename OrderedMapValue<K,D>& OrderedMap<K,D>::operator[](const K&);
     // snip...
};

class MyClass
{
public:
    MyClass(std::string s) : _my_data(s) {}
private:
    std::string _my_data;
};

以下代码有效:

OrderedMap<std::string,MyClass*> omap;
omap["MyKey"] = new MyClass("dummy");

但是,这段代码没有:

OrderedMap::iterator iter = omap.find("MyKey");
MyClass * obj = iter->second;
delete obj;
iter->second = new MyClass("dummy");

假设我做了什么 a) 结构愚蠢或 b) 不必要的复杂,应该怎么做?

我意识到我很可能在这里重新发明轮子,但同样,这项工作主要是为了增加我对 STL 容器、它们的设计模式和正确使用的知识。

提前感谢您提供任何见解,

【问题讨论】:

  • 迭代器的用法不应该是iter-&gt;second吗?其中iterOrderedMap::iterator*iterOrderedMapValue
  • 没错——输入答案。
  • 你是对的,我接受了你的回答。从概念上讲,您确实抓住了所需内容的精髓。当我仔细研究 TYPE& operator[] 方法时,我意识到有一些问题需要解决,以便标记为可接受解决方案的代码不会误导人们。我的(好的)意图是提供一个经过验证的解决方案,但我现在只是回到这个问题。
  • 当你说“这段代码不[工作]”时,是什么意思?不会编译?不会链接?抛出异常?崩溃?电脑着火了?

标签: stl containers


【解决方案1】:

我现在没有编译器来测试这个,所以可能会出现错误,但我认为你希望它更像:

template <typename K, typename D>
class OrderedMap
{
private:
        std::map<K,size_t> &m;
        std::vector<D> &v;
public:
    typename pair<K,D> TYPE;

        TYPE& operator[](const K &k)
    {
        return v[ m[ k ]];
    }

    TYPE& operator[](size_t idx)
    {
        return v[ idx ];
    }

    pair<iterator,bool> insert( const TYPE& pair )
    {
        map<K, size_t>::const_iterator iter;
        iter = m.find( pair.first );

        if( iter != m.end() )
            return make_pair( v[ iter.second], false );

        m.insert( make_pair( pair->first, v.size() ));
        v.push_back( pair->second );

        return make_pair(  v.last() , inserted );
    }

    iterator &begin()
    {
        return v.begin();
    }
    // etc
};

【讨论】:

  • 是的——这正是我想要的。感谢您花时间提供样品。
  • OrderedMap 应该按值保存地图和矢量,而不是引用。 TYPE 应该是 pair&lt;const K,D&gt;,以匹配地图的工作方式。另外,他可能想要operator[](const K&amp;) to return a D&`。
【解决方案2】:

OrderedMapValue::operator=,你有:

    std::map<K,size_t>::const_iterator iter = m.find(first_ref);

first_ref 是什么?该代码没有在其他地方引用它(没有双关语)。在我看来,它可能是旧实现的痕迹,在其他地方被公共成员取代

const K&amp; first

这可能是问题吗?

EDIT 来自 cmets:代码没有显示 first_ref 在任何地方初始化;所以据我所知,对m.find(first_ref) 的调用正在搜索一个空字符串,而不是 OrderedMapValue 的键。

【讨论】:

  • first_ref 是 OrderedMapValue 的非常量私有成员。我试图保留第一个 const,但仍然给自己一个设置关键成员的方法。
  • 但是 first_ref 是在哪里初始化的呢?据我所知, m.find(first_ref) 正在搜索一个空字符串,而不是您要覆盖的字符串。
  • Dan,为了保持代码简洁,我编辑了您需要查看的代码。事后看来,我可能应该忽略这个细节,因为本次讨论不需要它......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多