在 std::vector 中自动检查边界
Automatically check bounds in std::vector
在积极开发使用 std::vector
的 class 期间,经常会发生索引越界的情况。 (有关实际示例,请参阅 this code review question。)使用 operator[]
时,这会导致未定义的行为。不过,[]
语法易于阅读,比编写 .at()
.
更方便
因此我想使用 []
运算符编写我的代码,但同时启用了边界检查。测试代码后,删除边界检查应该很容易。
我在想下面的代码:
util::bound_checked<std::vector<int>> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_back(4);
std::cout << numbers[17] << "\n";
对我来说,这个实用程序模板似乎非常简单,我希望它存在。可以?如果有,用什么名字?
我认为不存在这样的东西,但创建它相当容易:
template <class Container>
struct bound_checked : public Container
{
using Container::Container;
auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
{ return this->at(i); }
auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
{ return this->at(i); }
};
请注意,上面实际上使用了一种不鼓励的做法,即public继承自标准容器(不是为其设计的)。我对您的问题的理解是,此包装器仅用于测试目的,这很好。但是,如果您希望它保留在生产环境中 并且 想要非常安全,请使用非 public 继承:
template <class Container>
struct bound_checked : private Container
{
using Container::Container;
auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
{ return this->at(i); }
auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
{ return this->at(i); }
using Container::begin;
using Container::end;
using Container::at;
using Container::insert;
// ... you get the idea
};
Does it? If so, under which name?
我很确定它确实存在。如果启用了编译器内部 __DEBUG
构建宏,许多编译器会启用 std::vector<T>::at()
作为 std::vector::operator[]()
的实现。
Therefore I'd like to write my code using the [] operator, but at the same time have bounds checks enabled. After testing the code, it should be very easy to remove the bounds checks.
关于命名,我认为是 debug 与 release 构建。在没有 __DEBUG
定义的情况下编译代码时将删除检查。
如果您使用 GCC(可能是 MinGW),或 Clang 与 libstdc++(GCC 的标准库),那么 #define _GLIBCXX_DEBUG
会做您想要的。
或者更好的是,用标志定义它:-D_GLIBCXX_DEBUG
.
或者,还有 _GLIBCXX_ASSERTIONS
,它执行较少的检查,但编译(并且可能运行)更快。
To me, this utility template seems to be so straight-forward that I'd
expect it to exist
对于 gcc,它确实存在。 gcc libstdc++ 有一组调试容器。 std::vector
它有 __gnu_debug::vector
调试容器。参见 documentation。
在积极开发使用 std::vector
的 class 期间,经常会发生索引越界的情况。 (有关实际示例,请参阅 this code review question。)使用 operator[]
时,这会导致未定义的行为。不过,[]
语法易于阅读,比编写 .at()
.
因此我想使用 []
运算符编写我的代码,但同时启用了边界检查。测试代码后,删除边界检查应该很容易。
我在想下面的代码:
util::bound_checked<std::vector<int>> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_back(4);
std::cout << numbers[17] << "\n";
对我来说,这个实用程序模板似乎非常简单,我希望它存在。可以?如果有,用什么名字?
我认为不存在这样的东西,但创建它相当容易:
template <class Container>
struct bound_checked : public Container
{
using Container::Container;
auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
{ return this->at(i); }
auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
{ return this->at(i); }
};
请注意,上面实际上使用了一种不鼓励的做法,即public继承自标准容器(不是为其设计的)。我对您的问题的理解是,此包装器仅用于测试目的,这很好。但是,如果您希望它保留在生产环境中 并且 想要非常安全,请使用非 public 继承:
template <class Container>
struct bound_checked : private Container
{
using Container::Container;
auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
{ return this->at(i); }
auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
{ return this->at(i); }
using Container::begin;
using Container::end;
using Container::at;
using Container::insert;
// ... you get the idea
};
Does it? If so, under which name?
我很确定它确实存在。如果启用了编译器内部 __DEBUG
构建宏,许多编译器会启用 std::vector<T>::at()
作为 std::vector::operator[]()
的实现。
Therefore I'd like to write my code using the [] operator, but at the same time have bounds checks enabled. After testing the code, it should be very easy to remove the bounds checks.
关于命名,我认为是 debug 与 release 构建。在没有 __DEBUG
定义的情况下编译代码时将删除检查。
如果您使用 GCC(可能是 MinGW),或 Clang 与 libstdc++(GCC 的标准库),那么 #define _GLIBCXX_DEBUG
会做您想要的。
或者更好的是,用标志定义它:-D_GLIBCXX_DEBUG
.
或者,还有 _GLIBCXX_ASSERTIONS
,它执行较少的检查,但编译(并且可能运行)更快。
To me, this utility template seems to be so straight-forward that I'd expect it to exist
对于 gcc,它确实存在。 gcc libstdc++ 有一组调试容器。 std::vector
它有 __gnu_debug::vector
调试容器。参见 documentation。