编译std :: vector的时间触发范围检查

时间:2014-06-16 14:29:35

标签: c++ c++11 vector

目标:

我希望我的调试版本具有std::vector operator []的范围检查版本,并且在发布模式下没有范围检查。

调试模式下的范围检查显然对调试有好处,但是在我的发布代码中会导致速度减慢5% - 10%,我希望避免这种情况。

可能的解决方案:

我在Stroustrup的“The C ++编程语言”中找到了一个解决方案。他做了以下事情:

template <class T>
class checked_vector : public std::vector<T> {
    public:
        using std::vector<T>::vector;

        //override operator [] with at()
};

这是有问题的,因为它继承自具有非虚拟析构函数的类,这是危险的。 (the Lounge was not too fond of that solution。)

另一个想法是这样的一个类:

template <class T>
class checked_vector {
    std::vector<T> data_;

    public:
        //put all public methods of std::vector here by hand

};

这既繁琐又会产生大量的复制粘贴,这也很糟糕。

上述解决方案的优点在于我可以在makefile中使用宏定义来打开和关闭它们。

问题:

  1. 有更好的解决方案吗? (如果没有,为什么不呢?)
  2. 如果没有,上述其中一项是否可以接受? (我知道这个是基于意见的,如果可能,请关注第1号。)

2 个答案:

答案 0 :(得分:12)

如果我没弄错,这是Visual Studio的常见情况。使用g ++,您必须使用-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC调用编译器。 (你很可能不需要这三个,但我全部使用 三个系统地。)与其他编译器,检查文​​档。标准中未定义行为的目的正是为了允许这种事情。

答案 1 :(得分:4)

按优先顺序递减:

  • 如果您使用迭代器,范围和迭代而不是索引到容器中,问题就会消失,因为您不再传递需要检查的任意索引。此时,您可以决定使用at替换需要索引的任何剩余代码,而不是使用特殊容器。

  • 按照其中一条评论中的建议,使用算法扩展而不是继承。这几乎肯定会完全内联,并且与使用算法的标准一致,而不是与其他成员函数一致。它还具有使用具有operator[]at的任何容器的优势(因此它也适用于deque):

    template <typename Container>
    const typename Container::value_type& element_at(const Container& c, int index)
    {
        // Do checked code here.
    }
    
  • 私有地将std::vectorusing所需的方法继承到子类中。那么至少你不能不正当地破坏你的孩子载体。