std::array专家解释了编程时C++ 11 的优点,但我希望从编译器中获得一些东西.能够打开.at()在编译使用的代码时使用时默认的范围检查[].
检查范围违规尤其是对于多维数组可能是有益的,因为在这种情况下,范围违规不太可能导致segfault(因为你经常在内部数组周围拥有内存,所以[5000][-123]仍然可能指向你拥有的内存).
所以我想知道是否有一个开关可以编译成检查范围的机器代码:
const uint32_t dim1=10*1000,dim2=3;
std::array<std::array<int, dim2>, dim1> test_2Darray;
int undefined_value=test_2Darray[dim2-1][dim1-1];
std::cout<<"ouch ("<<undefined_value<<")"<<std::endl;
int ok_value=test_2Darray[dim1-1][dim2-1];
std::cout<<"OK ("<<ok_value<<")"<<std::endl;
// test_2Darray.at(dim2-1).at(dim1-1); -->terminate called after throwing an instance of 'std::out_of_range'
// what(): array::at
Run Code Online (Sandbox Code Playgroud)
如果你问为什么我不切换到.at()- 我可能需要性能,我也有很多[]已编写的代码,而且我不够聪明,不能替代1D更换2D阵列.
我使用GCC 4.6
看起来gcc 4.6附带的数组还没有调试模式.可以理解,因为C++ 11支持仍然是实验性的.
有一个标志_GLIBCXX_DEBUG通常用于打开调试模式.如果你查看/usr/include/c++/4.6/debug/vector:313,你会看到operator[]:
__glibcxx_check_subscript(__n);
Run Code Online (Sandbox Code Playgroud)
现在,这可能是超级邪恶(我的意思是真的很邪恶),但看起来我们可以有条件地将它添加到数组中.更改/usr/include/c++/4.6/array的第148-154行:
reference
operator[](size_type __n)
{ return _M_instance[__n]; }
const_reference
operator[](size_type __n) const
{ return _M_instance[__n]; }
Run Code Online (Sandbox Code Playgroud)
至:
reference
operator[](size_type __n)
{
#ifdef _GLIBCXX_DEBUG
__glibcxx_check_subscript(__n);
#endif
return _M_instance[__n];
}
const_reference
operator[](size_type __n) const
{
#ifdef _GLIBCXX_DEBUG
__glibcxx_check_subscript(__n);
#endif
return _M_instance[__n];
}
Run Code Online (Sandbox Code Playgroud)
这意味着您可以像对向量和其他stl调试一样启用对数组的边界检查 - 通过添加-D_GLIBCXX_DEBUG到编译行.例如:
g++ someAwesomeProgram.cpp -D_GLIBCXX_DEBUG
Run Code Online (Sandbox Code Playgroud)
我只是看看gcc的树干,显然没有提到但_GLIBCXX_DEBUG数组:(.http://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/include/std/array
希望它不会太远.我想我们将很快就有安全的迭代器和调试模式中的所有数组.与此同时,这可能是我们的小秘密:-).
您可以模仿您想要的行为:
#include <array>
#include <cassert>
#include <iostream>
#ifndef NDEBUG
template <typename T, std::size_t N>
struct my_array : std::array<T,N> {
T& operator[](std::size_t n) {
assert(n < N);
return (*static_cast<std::array<T,N>*>(this))[n];
}
const T& operator[](std::size_t n) const {
assert(n < N);
return (*static_cast<const std::array<T,N>*>(this))[n];
}
};
#else
// I would use Alias templates here, but isn't supported on my compiler yet!
template <typename T, std::size_t N>
struct my_array : std::array<T,N> {
};
#endif
Run Code Online (Sandbox Code Playgroud)
它并不完全匹配std::array,但如果它对您很重要,则可以修复。然后将所有引用替换std::array为my_array,您将获得operator[]调试版本的范围检查。
(我已经使用模板别名来简化代码NDEBUG,但我还无法在我的编译器上实际测试它)