提问人:ander 提问时间:8/9/2023 最后编辑:LoSander 更新时间:11/11/2023 访问量:104
在调试模式下使用 std::vector 和 std::array 检查运算符 [] 的范围
Range checking for operator[] with std::vector and std::array in debug mode
问:
我正在编写一些数字C++,其中两者都用于代码的性能关键部分。我最好在调试模式下进行范围检查,以清除任何潜在的越界访问,但在发布版本中不提供开销。std::vector
std::array
operator[]
原则上,这可以通过断言语句轻松完成,但我不确定如何在不做坏事的情况下编辑 stl 库代码。我不会考虑使用该方法,因为这会在发布版本中产生开销。我正在使用 g++ 进行编译。我已经读到可以为 MSVC 编译器打开断言,但我使用的是 linux 和 g++,我认为这不是一个选项。at()
我已经为 创建了这个派生类,到目前为止,它对我的目的来说工作正常,但我怀疑这不是一个理想的解决方案。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::vector 的范围检查,但似乎从 std 类继承并不流行。std::array
std::vector
这篇文章的一个答案也建议使用标志,但我发现此检查从与工作正常的向量和数组无关的另一部分代码中产生了错误(尝试使用 yaml-cpp 库并使用 ).-D_GLIBCXX_DEBUG
operator[]
答:
0赞
user22361789
8/9/2023
#1
您可能需要:
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);
}
};
评论
1赞
ander
8/10/2023
后一种解决方案基本上是我在帖子中展示的,但是我无法为 std::array 复制相同的解决方案
0赞
8/10/2023
@ander 对不起,冗余。我明白你的意思,但这是错误的,如果定义,那么你的类甚至不会有这些运算符重载NDEBUG
Vector
评论
foo #if DEBUG .at(42); #else [42]; #endif
foo.at(42);
foo[42];
vector
-D_GLIBCXX_DEBUG
,但我发现此检查从代码的另一部分产生了错误”然后那部分代码被窃听了,修复它!