代码之家  ›  专栏  ›  技术社区  ›  thecoshman

在执行之后,类是否应该执行边界检查

  •  1
  • thecoshman  · 技术社区  · 14 年前

    假设我有一个三角形类,定义如下

    class Triangle{
    vertex3D vertexs[3];
    public:
    vertex* GetVertex(int vertexNumber);
    }
    

    现在对于大多数普通的应用程序来说 GetVertex 应该确保 vertexNumber 是在尝试返回顶点指针之前的有效索引。我想说,如果 顶点数 是无效的,但那不是我真正想要的。

    在游戏中,检查 顶点数 所有的时间都是有效的可能会占用一点时间,这会更快 获取顶点 假设只传递有效值。

    那么,三角航空以轻微的业绩提升为名义,基本上是把谨慎抛到九霄云外,这是否可以接受呢?

    如果我在debug中进行了边界检查,但没有发布,那么我如何自动执行此操作,以便不必编辑代码?什么编译时开关之类的?会使用 #ifdef debug 什么工作?我在哪里可以找到更多关于这个的信息?

    8 回复  |  直到 5 年前
        1
  •  5
  •   James McNellis    14 年前

    您应该检查调试生成中的边界。

    如果您确信您的代码是正确的(因此,您已经进行了代码检查并对其进行了广泛的测试),那么为了性能起见,可以在发布版本中不进行边界检查。

    如果要在调试生成中测试边界,而不是在发布生成中,则可能应该在调试生成中使用断言。断言应用于验证总是正确的事情。如果不检查函数内部的边界并且代码正确,则该值永远不应超出边界。

        2
  •  4
  •   aschepler    14 年前

    在登记处登记。当您有一个正在运行的程序时,您可以对其进行分析,并找出您可能在哪些地方进行更改,这些更改实际上有助于提高性能。那些地方可能根本不是你所期望的。

        3
  •  3
  •   Kos    14 年前

    如果 vertexNumber 不是一个直接来自外部输入的值,那么我相信你可以假设它总是有效的,也就是说,你承认A的存在。 合同 说“当vertexNumber为0、1或2时,此函数将正常工作”。然后,就代码正确性而言,类本身可以被理解为“正确和安全的”,您只需要担心客户端(这个类的用户)以正确的方式使用它——即不违反约定。

    通常完美的工具是在类方法中使用assert()来检查契约是否满足。然后,您将在 debug release 建造。

        4
  •  2
  •   sbi    14 年前

    如果该类在应用程序代码(仅在一个应用程序中使用的代码)中, 测量 性能增益是否相关,然后决定是否在释放模式下删除he检查。(让它们处于调试模式。)

    如果该类在库代码中,则由设计决定。你想让你的班级 尽可能安全 尽快 ? 既然这是图形代码,您可能需要后者。(这也在以速度为目标的STL中流行起来。)

        5
  •  1
  •   vitaut    14 年前

    我认为根本不做边界检查不是一个好办法。 如果你关心性能,在这种情况下至少使用 assert 可以在发布配置中禁用。

        6
  •  1
  •   Vatsan    14 年前

    …很长一段时间 …性能略有提高

    你得先决定哪个是真的。我会说写两个版本,并首先测量性能差异。或者更好的方法是,编写带有检查、测量和决定性能是否低于您的期望/需求的版本。如果是,那么就开始优化。我想在这一点上,为了性能而取消边界检查(如果可以证明它的性能更高,足以做出显著贡献)可能会成为一个更容易、更明智的选择。

    如果决定删除边界检查,则按合同设计:-)

        7
  •  1
  •   Community CDub    8 年前

    你为什么要 Triangle 一个物体?它看起来像一个简单的数据保存器。它不是多态使用的。它没有任何行为。它不是一个物体。让它成为一个带有公共数据的简单POD结构, 尤其地 如果你担心表现。

    当来电者试图使用 vertexNumber := 0xdeadbeef ,访问冲突发生在尝试公开使用数组的错误调用方中,而不是在没有错误的帮助程序填充中。这在调试环境中可能意义不大,但是当您得到一个不包含完整回溯的crashdump报告时,这是一个问题。

    道具 jalf 对于 an in-depth rant discussion I can link .

        8
  •  1
  •   Greg Domjan    14 年前

    合同设计,埃菲尔和“面向对象的软件构造,Myer”一书都会说,你应该将这种超出范围的问题定义为你可以从最终产品中编译出来的断言。断言定义了整个系统的数学确定性。