【问题标题】:Disabling bounds checking for c++ vectors禁用 C++ 向量的边界检查
【发布时间】:2010-03-05 03:15:53
【问题描述】:

使用 stl::vector:

vector<int> v(1);
v[0]=1; // No bounds checking
v.at(0)=1; // Bounds checking

有没有一种方法可以禁用边界检查而不必将所有at() 重写为[]?我正在使用 GNU 标准 C++ 库。

编辑:我在怀疑存在瓶颈的区域将at() 更改为[],这大大减少了计算时间。但是,由于我在开发代码和运行实验之间进行迭代,我想在开发期间启用边界检查,并在我真正运行实验时禁用它。我想 Andrew 的建议是最好的解决方案。

【问题讨论】:

  • 目的是什么?可能有更好的方法。
  • 您应该能够使用正则表达式将at() 替换为[],并设置断点以帮助验证所有实例都已被替换。不是说一个滑过会是一场灾难,关心的只是性能,对吧?
  • 您为什么要这样做?如果您的答案是性能,那么请告诉我您已经分析并发现这是您的瓶颈。如果是这种情况,那么可以,将您的 at()s 重写为 []。否则,顺其自然。
  • @Adam:也不是所有的ats,只是热点。 :-P
  • 您应该查明瓶颈的确切位置。也许您的代码在 malloc() 中花费 80% 的时间与边界检查无关:)

标签: c++ g++ libstdc++


【解决方案1】:

如果您真的想这样做(至少是为了进行快速而肮脏的分析比较),如果您没有其他 at()s,这将起作用

#define at(x) operator[](x)

如果您想保留at() 用于开发并在生产中使用operator[],只需将其包装在#ifdef 中即可。

如果您有其他 at()s,您可以随时编辑您的 #included &lt;vector&gt; 文件。

【讨论】:

  • +1 迟到了,但提供了很好的建议。这绝对是描述某些东西的快速而肮脏的方式。
【解决方案2】:

没有。 std::vector::at 的边界检查是由标准指定的,没有符合标准的 C++ 实现可以偏离它。

【讨论】:

    【解决方案3】:

    也许更好的解决方案是使用[] 并使用标准库的检查实现进行调试。

    【讨论】:

      【解决方案4】:

      根据您想要打开/关闭边界检查的评论,您可以使用包装模板功能:

      template <class T>
      inline typename T::reference deref(T &cont, typename T::size_type idx)
      {
      #if BOUNDS_CHECK
          return cont.at(idx);
      #else
          return cont[idx];
      #endif
      }
      
      template <class T>
      inline typename T::const_reference deref(const T &cont, typename T::size_type idx)
      {
      #if BOUNDS_CHECK
          return cont.at(idx);
      #else
          return cont[idx];
      #endif
      }
      

      您必须修改您的代码才能启用此功能,但一旦您将其设置到位,您就可以根据需要打开或关闭绑定检查。

      我承认它看起来有点难用:

      deref(vec, 10) = ...;
      

      【讨论】:

      • 这应该是公认的答案,因为它运行良好并且不会破坏不相关的代码,例如 Andrew Stein 的#define 解决方案。
      【解决方案5】:

      不是标准方式。您可以在编译器中关闭异常。您可以通过-fno-exceptions 使用 gcc 来做到这一点。

      不过,您应该警惕这样做;您的库(包括标准库)在关闭异常的情况下可能无法正常运行。检查您的文档和this one on the gcc mailing list 之类的线程。

      【讨论】:

        【解决方案6】:

        当您总是想要检查时,请使用at()。另请注意,这会在错误时引发异常,因此它可能是可恢复的。如果您想要更快的、未经检查的访问器,请使用[],但使用它的算法应该经过彻底测试,因为故障模式更严重(未定义的行为)。

        在 Linux 上使用 GCC 时检查[] 的开发模式边界的几种方法:

        其他一些有趣的讨论:vector::at vs. vector::operator[]

        【讨论】:

          【解决方案7】:

          在您自己的命名空间中派生您自己的向量类,例如“uncheckedvector”,并覆盖基本向量类型的 at() 以使用数组索引。

          然后使用“使用 uncheckedvector::vector”将让你在任何地方覆盖你对 vector 的所有使用。 但是,如果您在任何地方使用完全限定类型,这将不起作用。

          【讨论】:

          • -1:从不继承自 STL 类型,它们缺少虚拟析构函数。
          【解决方案8】:

          如果您有相当一致的访问模式(即/非随机访问),而不是使用at()[],避免范围检查的一种方法是使用迭代器,使用begin()end()advance() 甚至更好,通过使用标准算法。

          虽然这并不能解决纠正 at() 进行范围检查的根本问题,但标准库 (MSVC) 的一些实现已经检查了某些类型构建的迭代器

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-10-17
            • 1970-01-01
            • 1970-01-01
            • 2015-08-29
            • 2023-03-03
            • 2013-06-22
            • 2010-09-19
            相关资源
            最近更新 更多