c++ 在调试模式下使用std::vector和std::array检查operator[]的范围

rkue9o1l  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(85)

我正在写一些数值C++,其中std::vectorstd::array都被用于代码的性能关键部分。最好我希望operator[]在调试模式下进行范围检查,以清除任何潜在的越界访问,但在发布构建中不提供开销。
原则上,这可以很容易地用assert语句完成,但我不确定如何在不做坏事的情况下编辑stl库代码。我不会考虑使用at()方法,因为这也会在发布版本中产生给予开销。我使用g进行编译。我读到MSVC编译器可以打开assert,但我使用的是Linux和g,我不认为这是一个选择
我已经为std::vector创建了这个派生类,到目前为止,它对我的目的来说工作得很好,但我怀疑这不是一个理想的解决方案。

template <typename T> class Vector final : public std::vector<T> 
{ 
public: 
    using std::vector<T>::vector; 
#ifndef NDEBUG 
    T &operator[](size_t i) 
    { 
        assert(i < this->size()); 
        return *(this->_M_impl._M_start + i); 
    } 
    const T &operator[](size_t i) const 
    { 
        assert(i < this->size()); 
        return *(this->_M_impl._M_start + i); 
    } 
#endif 
};

字符串
我无法为std::array创建一个类似的派生类而没有问题。这篇文章解决了std::vector的问题:Compile time triggered range check for std::vector,但似乎从std类继承并不流行。
这篇文章的一个答案也建议使用-D_GLIBCXX_DEBUG标志,但我发现这个检查产生了与向量和数组无关的另一部分代码的错误,这些代码工作正常(尝试使用yaml-cpp库并使用operator[]访问根)。

x7yiwoj4

x7yiwoj41#

您可能需要:

template <typename T> 
class Vector final : std::vector<T> { ... };

int main() {
    Vector<int> v;

#ifndef NDEBUG
    v[1];    
#else 
    v.at(1);
#endif

    return 0;
}

字符串
或者修改Vector类:

template <typename T> 
class Vector final : std::vector<T> { 
public:
    using std::vector<T>::vector; 
 
    T &operator[](std::size_t i) { 
#ifndef NDEBUG 
        assert(i < this->size()); 
#endif
        return *(this->_M_impl._M_start + i); 
    } 

    const T &operator[](size_t i) const { 
#ifndef NDEBUG 
        assert(i < this->size()); 
#endif
        return *(this->_M_impl._M_start + i); 
    } 
};

相关问题