在不使用它的情况下初始化可能无效的引用是否合法?

时间:2013-06-15 08:49:38

标签: c++ c++11 reference

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

#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:即使在使用-Wall-g进行编译+运行时,gcc也没有抱怨。

编辑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 */ ;

3 个答案:

答案 0 :(得分:3)

不,合法。您正在使用n声明中的向量读取数据,因此您的程序具有未定义的行为。

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:0)

不,有两个原因:

  1. 标准状态(8.3.2):

      

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

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

  3. 因此,您的程序格式不正确(项目符号1)并调用未定义的行为(项目符号2)。