尝试更改_arr [3]时为什么没有引发异常?

时间:2019-07-19 10:47:38

标签: c++

我有这段代码,当试图在Container中到达_arr的第三个索引时,应该抛出一个异常。它也不例外,我不明白为什么。

删除构造函数会使它引发异常,这确实很奇怪。

class X {
public:
    X(int x) { std::cout << x - 1; }
};

template <class T, int d=3>
class Container {
    T* _arr;
public:
    Container():_arr(new T[d]){ }
    void setItemAtIndex(T item, int index) { _arr[index] = item; }
    X getItemAtIndex(int index) { return _arr[index]; }
};

int main()
{
    Container<int> container;
    for (int i = 1;i < 4;i++) {
        container.setItemAtIndex(i, i);
        X x = container.getItemAtIndex(i);
    }
    return 0;
}    

我希望抛出一个异常,但实际上它输出“ 012”。

2 个答案:

答案 0 :(得分:2)

C ++遵循这种哲学(尽管有一些例外情况违背了它)“不用为不需要的东西付钱” 。在超出数组边界时引发异常将需要进行显式检查。但是,如果您已经知道不能超过?

for(size_t i = 0; i < sizeof(someArray)/sizeof(*someArray); ++i)
    someArray[i] = 0; // i CANNOT be outside array boundaries, so why check???

这可以使C ++快速运行,但是另一方面,如果需要 ,则将这些检查强加给(就像访问器函数中一样)。正是由于这个原因,std::vector同时提供了operator[](未选中)和at(选中,超出当前大小会引发异常)。

如果您超出范围访问数组,则会调用未定义的行为。您可能会离开,因为可能会在阵列中分配一些额外的内存。如果超出数组边界足够,则可能会看到与省略构造函数时相同的“异常”(使指针未初始化为某个随机值)。实际上,这并不是C ++的例外。这是一种访问冲突(读取程序中不存在或无法访问的内存地址),很可能被操作系统检测到,并通过某种适当的方式处理了该问题(例如linux向程序发送SIG_SEGV信号)。

答案 1 :(得分:1)

在C ++中没有规则说访问数组超出范围时必须抛出异常。这只是undefined behaviour的情况。

删除构造函数会导致它引发异常,这确实很奇怪。未定义的行为是无法预测的。我猜想您的系统最好是通过未初始化的指针来捕获访问,而不是对数组进行超出范围的访问。