目标:
我希望我的调试版本具有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中使用宏定义来打开和关闭它们。
问题:
答案 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::vector
和using
所需的方法继承到子类中。那么至少你不能不正当地破坏你的孩子载体。