实现operator []时,如何包含边界检查?

Jam*_*tta 4 c++ operator-overloading

首先,我为这个简单问题的漫长导致道歉.

我正在实现一个类,它在空间填充曲线上作为非常长的1维索引,或者表示索引对应的笛卡尔坐标的n元组.

class curvePoint
{
public:
    friend class curveCalculate;

    //Construction and Destruction
    curvePoint(): point(NULL), dimensions(0) {}
    virtual ~curvePoint(){if(point!=NULL) delete[] point;}

    //Mutators
    void convertToIndex(){ if(isTuple()) calc(this); }
    void convertToTuple(){ if(isIndex()) calc(this); }
    void setTuple(quint16 *tuple, int size);
    void setIndex(quint16 *index, int size);
    void setAlgorithm(curveType alg){algorithm = alg;}

    //Inspectors
    bool isIndex(){return current==Index;}
    bool isTuple(){return current==Tuple;}
    size_t size(){return dimensions;}
    quint16 operator[](size_t index);

    enum curveType{HilbertCurve, ZCurve, GrayCodeCurve};
    enum status{Index, Tuple};

private:
    curveCalculate calc;
    curveType algorithm;
    quint16 *point;
    size_t dimensions;
    status current;
};
Run Code Online (Sandbox Code Playgroud)

(点指向的数组长度是维度)

无论如何在operator []的实现中我想知道实现边界检查的最佳方法是什么.我想尽可能避免抛出异常,并且数组中的每个数字都可以使用全范围的值,因此在出现越界错误时也不能返回特殊值;

虽然在类定义中实现,但我正在考虑这样的事情:

quint16 curvePoint::operator[](size_t index)
{
    return point[ index % dimensions ];
}
Run Code Online (Sandbox Code Playgroud)

这使得我们永远不会离开数组的界限,如果有详细记录,我认为它会没事; 尽管如此,我对这一特定实施情况持谨慎态度.

这对其他人来说是否可以接受?在满足我的约束条件的同时还有其他方法可以进行边界检查吗?

编辑:Hilbert曲线等事物的计算非常混乱,杂乱得足以让我不想要stl库的附加接口.

另外,因为每次查询多维数据库时我都必须转换成千上万的这些,我不希望混合中的stl函数调用的额外成本,如果可能的话.

我更喜欢断言的想法; 但是,如果我没记错的话,发布版本中断了吗?

我想我可以使用异常,这似乎是每个人都支持的异常,但我使用的是Qt库,避免了性能和可移植性的异常,我希望也能这样做.

MSa*_*ers 12

最简单的解决方案是像C++本身那样做.这会限制用户体验的惊喜数量.

C++本身相当一致.如果使用超出范围的数组索引,则内置[]指针并std::vector::operator[]具有未定义的行为.如果你想要边界检查,请明确并使用std::vector::at

因此,如果您为您的班级做同样的事情,您可以将越界行为记录为"标准".


Dan*_*nas 10

无论如何在operator []的实现中我想知道实现边界检查的最佳方法是什么.我想尽可能避免抛出异常,并且数组中的每个数字都可以使用全范围的值,因此在出现越界错误时也不能返回特殊值;

然后剩下的选项是:

  • 设计灵活.你做了什么."修复"无效输入,以便它尝试做一些有意义的事情.优点:功能不会崩溃.缺点:访问越界元素的无能的调用者会因此而产生谎言.想象一下10层楼的建筑,楼层为1到10层:

你:"谁住在三楼?"

我: "玛丽".

你:"谁住在9楼?"

我:"乔".

你:"谁住在1,203楼?"

我:(等等...... 1,203%10 = 3 ......) >"玛丽".

你:"哇,玛丽必须从那里欣赏美景.那么她拥有两套公寓呢?"

  • 布尔输出参数指示成功或失败.此选项通常以不太可用的代码结束.许多用户将忽略返回码.您仍然留下您在其他返回值中返回的内容.

  • 按合同设计.断言调用者在边界内.(对于C++中的实用方法,请参阅Miro Samek的异常或错误?或者Pedro Guerreiro在C++中简单支持契约式设计.)

  • 回来一个System.Nullable<quint16>.糟糕,等等,这不是C#.好吧,你可以返回一个指向quint16的指针.这当然有很多含义,我不会在这里讨论,这可能使这个选项无法使用.

我最喜欢的选择是:

  • 对于公开发布的库的公共接口:将检查输入并抛出异常.您排除了此选项,因此它不适合您.它仍然是公开发布的库的界面的选择.
  • 对于内部代码:按合同设计.


Tim*_*imW 7

对我来说,这个解决方案是不可接受的,因为你可以隐藏一个很难找到的bug.抛出超出范围的异常是要走的路,或者至少在函数中放置一个断言.

  • 最好遵循STL的例子,以保持一致性.operator []没有对最大性能进行边界检查,并且在(int idx)进行边界检查并抛出异常. (2认同)