1

考虑一段代码

int main(int argc,char* argv[]){
        int *arrPtr = new int[4];
        for (int i=0;i<4;i++)
                arrPtr[i]=i*2;


        for (int i=0;i<10;i++){
                arrPtr++;
                cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
        }
        cout<<endl;
        return 0; }

当我编译这个程序

g++ main.cpp -o main && ./main

它给了我

arrPtr [0] 2
arrPtr [1] 4
arrPtr [2] 6
arrPtr [3] 0
arrPtr [4] 135145
arrPtr [5] 0
arrPtr [6] 0
arrPtr [7] 0
arrPtr [8] 0
arrPtr [9] 0

当 arrPtr 未指向“有效”元素时,我希望能够检测(抛出或检查)。在上面的代码中,最后一个有效元素是 arrPtr[3]。

请不要“我也是”的答案!

4

4 回答 4

5

使用vector.

int main()
{
    std::vector<int> a(4);

    for (size_t i = 0; i < 4; ++i)
        a[i] = i * 2;
    for (size_t i = 0; i < 10; ++i)
        std::cout << i << ": " << a.at(i) << std::endl;
}

结果:

0: 0
1: 2
2: 4
3: 6
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
Aborted
于 2012-08-03T12:21:07.557 回答
2

其他人已经展示了这个具体问题的解决方案:使用std::vector而不是原始指针(无论如何都要这样做!)和元素访问通过.at().

但是,通常您应该确保代码中永远不会出现这种情况。越界错误不是您应该在运行时处理的情况,它们是代码中的错误,需要事先删除。

有几种策略——例如,不要使用索引访问。大多数这样的实例可以用迭代器访问代替,虽然它不是自动安全的,但是更难出错。

更好的是,尽可能避免循环并使用 C++ 标准库中的高阶算法。

例如,无循环代码的样子:

std::vector<int> arr;
std::generate_n(std::back_inserter(arr), 4,
    [] {
        static int current = 0;
        return current++ * 2;
    });
std::copy(begin(arr), end(arr), std::ostream_iterator<int>(std::cout, "\n"));

这种风格需要一些时间来适应,但它大大减少了在代码中出错的机会,并使某些错误类不可能成为专有的。

于 2012-08-03T12:30:29.690 回答
1

普通的 C 数组是不可能的。您可以使用 std::vector,它具有用于通过边界检查访问元素的 API。

于 2012-08-03T12:19:32.623 回答
0

这个话题已被广泛讨论。通常,在C语言中,如果事先不知道数组的一些信息,就无法检测指针是否指向数组中的某个位置。

正如@Charlie Martin 在他对这篇文章的回答中提到的那样,这是因为边界检查将花费额外的操作。由于C通常用于制作对速度敏感的程序(例如硬件驱动程序),因此边界检查不是在语言中实现的,而是由需要它的人自己实现的。

因此,如果要进行边界检查,则必须执行以下操作:

int *start = new int[4];
int size=4;
int *arrPtr;
...
for (int i=0,arrPtr=start;i<10;i++){
    arrPtr++;
    if(arrPtr>=start && arrPtr <start+size) // the boundary checking by yourself
       cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
}

通过这种方式,该语言可以让您决定是否值得和有必要使用额外的操作来进行边界检查。

当然,一旦您决定需要在程序中进行边界检查,就已经实现了更高级别的数据类型,例如vector.

于 2012-08-03T12:55:20.087 回答