2017-03-02 115 views
0

我期待下面的代码导致未定义的行为工作:在本地参考变量

#include <iostream> 
#include <vector> 

using namespace std; 

template <class T> 
void incrementElements(vector<T> &v) 
{ 
    for(typename vector<T>::size_type index = 0; index < v.size(); ++index) 
    { 
     T& local = v[index]; 
     ++local; 
    } 
} 

int main(){ 
    vector<int> v; 
    for(int i = 0; i < 10; ++i) 
    { 
     v.push_back(i); 
     cout << v[v.size() - 1] << endl; 
    } 
    incrementElements(v); 
    for(vector<int>::size_type index = 0; index < v.size(); ++index) 
    { 
     cout << v[index] << endl; 
    } 
    return 0; 
} 

我给一个参考我的矢量元素给一个局部变量,然后增加它。 我预计,当局部变量的生命周期结束矢量的记忆将得到清理,以及导致空引用。 除了它给出了正确的输出。
这是编译器是足够聪明和固定这种行为或者这是实现代码能够接受的方式?

我用G ++(GCC)5.3.0

编辑
要指定我的主要困惑编译,我错了的假设下,一个参考产生某种硬链接,这是等同于如何原始变量被声明。
在我目前的理解,是使用相同的指针如下:

for(typename vector<T>::size_type index = 0; index < v.size(); ++index) 
    { 
     T* local = &v[index]; 
     ++(*local); 
    } 
+3

参考消失,而不是在元件内部'v'。同样做的是你想要的是未定义行为的可能结果,所以这不是检查它的好方法。 – nwp

+0

参考资料永远不会缩短任何事物的寿命。你的循环体等同于'++ v [index];'。 – molbdnilo

+0

载体的寿命结束时'main'退出:(附注C++中的单词“参考”并不意味着同样的事情,在Java和类似的语言“参考”字)。您可以在该生命周期中为矢量添加和删除名称;但是它的使用寿命保持原样 –

回答

2

几件事情需要注意:

  • 当你有UB程序可以以任何方式表现,包括可能性它的工作“正常”(即给预期的结果)
  • 有没有这样的事情“空引用”

您的代码本身很好,可以引用一个对象超出范围。它不是确定有被引用到走出去的范围参考不前的对象(但要注意,有些时候常量引用延长对象的生命周期),然后尝试通过参考使用。

+0

当你有UB时,程序可以以任何方式运行,包括从你的硬盘中删除所有数据;-) – MaxV

+0

因此,在这种情况下,引用的行为是相同的,就好像我已经采用了指向元素的指针? – turoni

+1

@turoni,那会有点不真实。把它看作一个别名。当块开始时,你会说“从现在开始,我将把这个特定的向量元素称为'本地'”。块结束并且引用超出范围时,您只需停止将此特定向量元素称为“本地”,这当然不会影响引用的元素本身。 – SingerOfTheFall

1

你的代码没问题。

for(typename vector<T>::size_type index = 0; index < v.size(); ++index) 
{ 
    T& local = v[index]; 
    ++local; 
} 

类似于

int i = 0; 
{ 
    int& ref = i; 
    ++ref; // Changes the value of i 
} 

在那结束时,你希望看到的i价值为1

  1. ref只生活在嵌套范围。它不能在嵌套作用域之外使用。它不会改变i的使用寿命。
  2. 价值i被嵌套范围内通过ref改变。在嵌套作用域结束后,i继续保持活动状态。