【问题标题】:I want to return a VALUE for given KEY for map<> in c++. What to return in case KEY is not present in map<>?我想在 C++ 中为 map<> 的给定 KEY 返回一个 VALUE。如果 KEY 不存在于 map<> 中,返回什么?
【发布时间】:2012-03-08 17:50:28
【问题描述】:

我用模板写了类。类有 map 作为成员和一些 getxxx() / setxxx() 成员函数。

template<typename T1,typename T2>
class C1{
    map<T1,T2> M;
public:
    map<T1,T2> getM();
    T2 getMvalue(T1 Key);
    void setM(T1 key,T2 Value);
};

这里我想实现getMvalue(),它接收key作为参数,如果“key”在mapM中可用,则返回相应的“value”。

它看起来像......

template<typename TKey,typename TValue>
T2 C1<T1,T2>::getMvalue(T1 Key){
    if(M.count(Key)>0)
        return M[Key];
    else
        return(???);
};

在这里我需要使用一些东西来代替???。请记住,函数的返回类型是 T2,它可以是任何取决于用户决定的类型。 我该如何替换“???”和什么?

【问题讨论】:

    标签: c++ templates map return-value


    【解决方案1】:

    我鼓励你使用TryGet 模式

    template<typename TKey,typename TValue>
    bool C1<T1,T2>::tryGetMvalue(T1 key, T2& value){
        if(M.count(key)>0) {
            value = objProperties[key];
            return true;
        }
        return false;
    };
    

    【讨论】:

    • 当你打败我时,这就是我正在建议的过程...... +1
    • map中会有数百个键值对,这样的类对象会有数千个。因此,在每个对象的 map 中搜索 KEY 时,时间复杂度会更高。在这种情况下,使用这种技术(使用 tryGet)会更好,如果 KEY 存在,则需要“两次”搜索。
    • @NDThokare:您可以使用find() 而不是count()[] 组合;那么只有一次搜索。
    • @paul23 即使没有返回值,它也会构造一个值。可选类型(例如boost::optional)拥有与std::pair&lt;bool, T&gt; 一样多的信息,但没有这个缺点。
    【解决方案2】:

    通过使用operator[],您已经将自己限制为仅存储可默认构造的值;所以你可以返回TKey() - 除非用户需要知道它是否真的被找到了。

    如果您不想要该限制,则必须将其更改为:

    auto found = map.find(key);
    if (found != map.end()) {
        return found->second;
    } else {
        return ???;
    }
    

    现在指示失败的最简单方法是将返回类型更改为指针(或者如果您想按值返回,可能是boost::optional),然后返回null(或boost::none);或者通过引用参数返回结果,并以布尔返回值表示成功;或抛出异常。

    【讨论】:

    • 有什么理由比指针更喜欢boost::optional?如果函数计算一个值,并且必须返回一个右值,那么像boost::optional(但名称更好)之类的东西是理想的,但是当你保证一个左值时,指针似乎更简单(至少对我来说)。
    • @JamesKanze:不特别;我只是想我会提到它。在您需要返回本地对象,因此无法返回指针的类似情况下,它会很有用。
    • 这周肯定要结束了。我刚刚看到boost::optional 突出显示,并错过了您还提出了一个指针的事实。 (我同意值得一提。虽然这个名字几乎不适合这种情况,而且在 Boost 之前的我们中的大多数人已经在我们的工具包中找到了一个更好命名的替代品。)
    【解决方案3】:

    你的选择是三个:

    1. throw 异常
    2. 修改签名以便您可以返回带外数据(这就是@JaredParsuggests
    3. 返回带内数据。

    如果您必须选择 3,我会返回默认值(这是 std::map::operator[] 所做的):

    template<typename TKey,typename TValue>
      T2 C1<T1,T2>::getMvalue(T1 Key){
        if(M.count(Key)>0)
          return M[Key];
        else
          return T2();
      }; 
    

    请注意,设计选择 #3 会导致错误。调用者无法区分“标称值”和“不存在”。


    附:如果您确实返回默认值,那么您的代码可能会简化为:
    template<typename TKey,typename TValue>
    T2 C1<T1,T2>::getMvalue(T1 Key){
      return M[key];
    }
    

    【讨论】:

    • 在第二种情况下,operator[]:返回对key为key的元素的值的引用,如果key不存在则插入一个key为元素的元素。我想避免。
    【解决方案4】:

    几种可能性。最简单的方法是让 getter 返回一个 指针,如果键不在地图中,则为空指针。 或者,您可以让它返回一个 Fallible(或 Maybe,或 不管你怎么称呼它);虽然一般来说是一个很好的解决方案,但似乎 在这里矫枉过正。或者最后,如果 对象不存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-14
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2014-10-24
      相关资源
      最近更新 更多