边界检查运算符[](int i)

时间:2011-11-29 14:32:52

标签: c++ visual-studio-2010

当他在容器中请求边界之外的元素时,如何将无效对象返回给用户。我不会抛出异常。

我编写了自己的模板哈希表

template <class Type1, class Type2> class wqHashTable
{

    public:
    template <class Type1, class Type2> 
        Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
        {
            if (goodId(idx))
            {
                return m_pValue[idx];
            }
            else
            {
                Type2* tValue = new Type2[1];   //TODO: How do we handle errors?

                return tValue[0];
            }
        }
    }

6 个答案:

答案 0 :(得分:2)

如果您不喜欢异常(出于任何不明原因,您应该在这里使用它们),请尝试Boost.Optional

boost::optional<Type2&> operator[](int idx) const
{
    if(good_idx(idx)
      return boost::optional<Type2&>(m_pValue[idx]);
    return boost::optional<Type2&>(); // uninitialized
}

致电代码:

boost::optional<the_type&> opt_ret = your_table[idx];
if(ret){
  the_type& ret = *opt_ret; // for convenience
  // valid idx, use ret
}

或者你可以按照std::vector的设计,只返回m_pValue[idx],无论好坏,并提供一个.at(int idx)方法进行边界检查(并抛出异常,如果检查失败)。

总而言之,没有理由不使用例外。其他答案已经详细说明了。

答案 1 :(得分:1)

throw(IDK为什么你不想这样做)return NULL;

另一种选择是在返回的类型中使用像“.thisIsErrorObject”这样的字段;这样,您可以构造自己的错误代码对象。

答案 2 :(得分:1)

我建议抛出异常,因为其他任何东西都会使用户代码中的控制流程复杂化(或被忽略并导致意外结果)。如果有一个迫切的理由不使用异常,那么下一件事就是实现Null对象模式(即有一个静态的 null 对象,当你无法返回一个真实的对象时,它会返回给用户的引用)。

在这种特殊情况下Null对象模式的问题在于,除非您创建单独的派生类型(繁琐,不是容器的角色,但可能适合应用程序的更大设计),否则该对象将无法与任何有效对象区分开来对象,你将强迫用户检查引用绑定的对象的地址,这意味着你回来了返回一个指针(可以自己为空,不需要提供Null对象)。

答案 3 :(得分:0)

如果您不想抛出异常,则需要知道自己想要做什么。例如,您可能希望有一个预定义的成员在超出边界的情况下返回引用。我认为你不想在这里new做任何事情,但话又取决于你的意图。

答案 4 :(得分:0)

我会assert(goodId(idx));return m_pValue[idx];

有点奇怪,用户应该如何知道存储中的索引。如果它是供内部使用的东西,断言可能是绝对足够的。

否则,也许使用标准关联容器的设计?

答案 5 :(得分:0)

template <class Type1, class Type2> class wqHashTable
{
    Type2 INVALID_ELEMENT;
public:
    bool last_access_valid;

    template <class Type1, class Type2> 
    Type2& wqHashTable<Type1, Type2>::operator[](int idx) const
    {
        last_access_valid = goodId(idx);
        if (last_access_valid )
            return m_pValue[idx];
        else 
            return INVALID_ELEMENT;
    }
}

这需要Type2作为默认构造,这不是你将永远保证的,但它很常见。来电者可以查看last_access_valid

的值

如果您打算使用这样的last_access_valid这样的话,我强烈建议我在https://stackoverflow.com/a/8088357/845092张贴一个类来保证每次都检查它,这样你就不会意外忘记。在这种情况下,last_access_valid的类型为ForceCheckError<bool>,如果调用者未检查,则assert