1

我想在某个循环中保存输入,创建对可能不存在的数组元素的引用。这样做合法吗?一个简短的例子:

#include<vector>
#include<iostream>
#include<initializer_list>
using namespace std;
int main(void){
    vector<int> nn={0,1,2,3,4};
    for(size_t i=0; i<10; i++){
        int& n(nn[i]); // this is just to save typing, and is not used if invalid
        if(i<nn.size()) cout<<n<<endl;
    }
};

https://ideone.com/nJGKdW可以很好地编译和运行代码(我在本地尝试使用 g++ 和 clang++),但我不确定我是否可以依靠它。

PS: gcc 都不会抱怨,即使编译+运行时使用-Walland -g

编辑 2:讨论集中在数组索引上。实际使用的代码std::list片段如下所示:

std::list<int> l;
// the list contains something or not, don't know yet
const int& i(*l.begin());
if(!l.empty()) /* use i here */ ;

编辑3:我正在做的合法解决方案是使用迭代器:

std::list<int> l;
const std::list<int>::iterator I(l.begin()); // if empty, I==l.end()
if(!l.empty()) /* use (*I) here */ ;
4

3 回答 3

3

不,这合法。您正在从声明中的向量读取数据超出范围,n因此您的程序具有未定义的行为。

于 2013-06-15T08:58:53.433 回答
0

如果规范“允许”这样做,我会感到惊讶。但是,它所做的是存储超出其分配范围的元素的地址,这在大多数情况下本身不会导致问题 - 在极端情况下,它可能会溢出指针类型,这可能会导致问题,我想。

换句话说,如果iWAY 超出 的大小nn,这可能是一个问题,不一定说i必须是巨大的 - 如果向量中的每个元素都是几兆字节(或 64 位机器中的千兆字节),你可以很快遇到地址范围问题。

但是不要让我引用规范 - 其他人可能会这样做。

编辑:根据评论,由于您请求的值的地址超出了有效大小,至少在调试版本中,这很可能导致vector实现断言或以其他方式“警告您这是错误的”。

于 2013-06-15T08:59:28.520 回答
0

不,有两个原因:

  1. 标准规定(8.3.2):

    应初始化引用以引用有效的对象或函数

  2. std::vector::operator[]保证即使N超过容器大小,该函数也不会抛出异常(不抛出保证,除了 之外没有边界检查at())。但是,在这种情况下,行为是未定义的。

因此,您的程序格式不正确(要点 1)并调用未定义的行为(要点 2)。

于 2013-06-15T10:07:42.907 回答