猿问

返回对本地或临时变量的引用

返回对本地或临时变量的引用

看下面的代码。我知道它不会返回局部变量的地址,但为什么它仍然有效并将imain()中的变量赋值为'6'?如果从堆栈内存中删除变量,它如何仅返回值?

#include <iostream>int& foo(){
    int i = 6;
    std::cout << &i << std::endl; //Prints the address of i before return
    return i;}int main(){
    int i = foo();
    std::cout << i << std::endl; //Prints the value
    std::cout << &i << std::endl; //Prints the address of i after return}


动漫人物
浏览 514回答 3
3回答

HUX布斯

你真是幸运。从函数返回不会立即擦除刚刚退出的堆栈帧。顺便说一下,你是怎么证实你有6回来的?表达式std::cout << &i ...打印的是地址i,而不是其值。

哆啦的时光机

返回引用或指向局部变量的指针是未定义的行为。未定义的行为意味着,标准将决策留给编译器。这意味着,未定义的行为有时效果很好,有时则不然。

噜噜哒

地址i永远不会改变main(),但其中包含的值将会改变。您正在引用局部变量并在该引用超出范围之后使用它。(不精确的语言警告)值6在堆栈上。由于在放入堆栈后没有对堆栈执行任何操作,因此6对它的引用仍将包含相同的值。所以,正如其他人所说,你很幸运。要查看有多幸运,请在调用后尝试运行使用堆栈的代码foo():#include&nbsp;<iostream>#include&nbsp;<ctime>#include&nbsp;<numeric>int&&nbsp;foo(){ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;6; &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;&i&nbsp;<<&nbsp;"&nbsp;=&nbsp;"&nbsp;<<&nbsp;i&nbsp;<<&nbsp;std::endl;&nbsp;//Prints&nbsp;the&nbsp;address&nbsp;of&nbsp;i&nbsp;before&nbsp;return &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;i;}long&nbsp;post_foo(int&nbsp;f){ &nbsp;&nbsp;&nbsp;&nbsp;srand((unsigned)time(0)); &nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;vals[10]&nbsp;=&nbsp;{0}; &nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;num_vals&nbsp;=&nbsp;sizeof(vals)/sizeof(vals[0]); &nbsp;&nbsp;&nbsp;&nbsp;for(&nbsp;size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;num_vals;&nbsp;++i&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;r&nbsp;=&nbsp;(rand()%2)+1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vals[i]&nbsp;=&nbsp;(i+f)*r; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;accum&nbsp;=&nbsp;std::accumulate(vals,&nbsp;&vals[num_vals],&nbsp;0); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;accum&nbsp;*&nbsp;2;}int&nbsp;main(){ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&i&nbsp;=&nbsp;foo();//&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"post_foo()&nbsp;=&nbsp;"&nbsp;<<&nbsp;post_foo(i)&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;&i&nbsp;<<&nbsp;"&nbsp;=&nbsp;"&nbsp;<<&nbsp;i&nbsp;<<&nbsp;std::endl;&nbsp;}当我通过post_foo()注释掉的调用运行它时,6仍然在堆栈上,输出是:002CF6C8&nbsp;=&nbsp;6002CF6C8&nbsp;=&nbsp;6...但是当我没有评论这个电话post_foo()并再次播放时,它6早已不复存在:001FFD38&nbsp;=&nbsp;6post_foo()&nbsp;=&nbsp;310001FFD38&nbsp;=&nbsp;258923464
随时随地看视频慕课网APP
我要回答