边界检查
宏 @boundscheck(...)
把代码块标记为要执行边界检查。但当这些代码块被被宏 @inbounds(...)
标记的代码包裹时,它们可能会被编译器移除。仅当@boundscheck(...)
代码块被调用函数包裹时,编译器会移除它们。比如你可能这样写的 sum
方法:
使用自定义的类数组类型 MyArray
,我们有:
当 getindex
被 sum
包裹时,对 checkbounds(A,i)
的调用会被忽略。如果存在多层包裹,最多只有一个 @boundscheck
被忽略。这个规则用来防止将来代码被改变时潜在的多余忽略。
There may be certain scenarios where for code-organization reasons you want more than one layer between the @inbounds
and @boundscheck
declarations. For instance, the default getindex
methods have the chain calls getindex(IndexStyle(A), A, i)
calls _getindex(::IndexLinear, A, i)
.
The overall hierarchy is:
checkbounds(A, I...)
throws an error if the indices are invalid, whereas checkbounds(Bool, A, I...)
returns in that circumstance. checkbounds_indices
discards any information about the array other than its axes
tuple, and performs a pure indices-vs-indices comparison: this allows relatively few compiled methods to serve a huge variety of array types. Indices are specified as tuples, and are usually compared in a 1-1 fashion with individual dimensions handled by calling another important function, checkindex
: typically,
so checkindex
checks a single dimension. All of these functions, including the unexported checkbounds_indices
have docstrings accessible with ?
.
If you have to customize bounds checking for a specific array type, you should specialize checkbounds(Bool, A, I...)
. However, in most cases you should be able to rely on checkbounds_indices
as long as you supply useful axes
for your array type.
If you have novel index types, first consider specializing checkindex
, which handles a single index for a particular dimension of an array. If you have a custom multidimensional index type (similar to CartesianIndex
), then you may have to consider specializing checkbounds_indices
.