通过超出范围的引用返回变量

时间:2017-12-09 20:51:00

标签: c++ pointers scope reference

int& foo()
{
    int i = 4;
    return i;
}

int main()
{
    int& j = foo();
    cout << j << endl;
    cout << j << endl;
    cout << j << endl;
    cout << j << endl;
    cout << j << endl;
    cout << j << endl;
    return 0;
}

在这里,我希望j的第一个cout输出垃圾,因为j引用的local变量i已超出范围。但是,如果我仍在cout的范围内,似乎始终是第一个4语句输出将输出的正确值。之后,每个cout语句都会打印相同值的垃圾。这是我得到的一些输出的例子:

4
528494
528494
528494
528494
528494
Press any key to continue . . .

为什么j不会立即在第一个cout语句中打印出垃圾。我不应该已经超出范围了吗?

1 个答案:

答案 0 :(得分:0)

规则不是&#34;在超出范围后使用变量会产生垃圾输出&#34;。根据所有C ++标准,使用对超出范围的变量的引用是未定义的行为。

未定义的行为意味着C ++标准不保证会发生什么。结果是,当行为未定义时,允许任何实际的可观察结果。垃圾输出只是一种可观察到的结果。

这意味着您所看到的行为的任何解释都将特定于您的实现(编译器,您选择的优化或调试设置等,主机系统的内存管理,......)。行为也可能随时间而变化,因为 - 当行为未定义时 - 不要求任何特定行为始终如一地发生。

作为一般性解释,在您的具体情况下,它可能与您的编译器如何管理程序对机器寄存器的使用有关。 i中的变量foo()可以存储在寄存器中,然后可以不立即清除该寄存器,因此在第一个4语句中从中检索值cout << j << endl 。然后输出流的工作(operator<<()endl的实现)可以在内部使用相同的寄存器 - 因为具有良好定义的行为的C ++代码绝对不能直接访问这些寄存器 - 因此覆盖它。

但这只是猜测。正如我所说,这取决于实施 - 这就是为什么我使用“&#34; may&#34;如此自由地在前一段。当行为未定义时(按标准),则允许编译器执行任何操作。通过调整优化设置或下次更新编译器,您可以看到完全不同的行为。不同的编译器也可能完全不同。