我正在使用C ++的基础知识并尝试了下面的代码行,
int& func()
{
int localnum = 10;
return localnum;
}
int main()
{
int &i = func();
cout<<"value : "<<i<<endl;
cout<<"value : "<<i<<endl;
return 0;
}
在这里,我返回一个局部变量作为参考(实际上我不应该这样做,但我只是为了学习行为而这样做。)
我认为即使func()
执行完成,localnum
的值仍将被保留,并且在任何进程使用内存空间之前不会被销毁(但设置一些位/标志以便剩余的进程处理这个内存块是免费的,可以使用它) - 纠正我,如果我错了
为了检查这一点,我打印了i
的值。就我而言,这是输出
值:10
价值:264952704
即使我使用指针并返回地址代替引用,这也是同样的情况。
我的问题是,我没有在这些版画之间运行任何过程,但价值仍在变化。这意味着我的系统中的任何其他进程都在这些打印之间使用localnum
的内存区域?
答案 0 :(得分:4)
如果你纯粹推理语言,这只是未定义的行为,所以理论上结果可能是任何东西。
根据实现的推理,不需要另一个进程来覆盖通常在堆栈中分配的局部变量。除此之外,任何对另一个函数的调用都可以。在这种情况下,第一次调用Reshape
对象的operator <<
涉及函数调用,该函数调用重用了cout
使用的堆栈区域,导致覆盖内存位置临时创建变量func()
的地方。
但同样,观察到的结果并不一致;它在很大程度上取决于实现,编译器,编译器选项等。
答案 1 :(得分:3)
使用<<
意味着相当多的活动,而不需要不同的过程。检查您引用的示例程序中所需的#includes
。顺便给出整个代码将被称为&#34; MCVE&#34;。 https://stackoverflow.com/help/mcve
实际上唯一能够改变&#34;你的&#34; stack 是相同的进程,甚至是该进程中的同一个线程。因为每个进程都有自己的堆栈。
你正在谈论的内存是堆栈。管理数据不过是指向内存的第一个可用部分的指针;也许隐含的知识总共有多大。即堆栈上的每个字节都没有单独的标志,这会增加堆栈所需的大量内存。
因为你得到了&#34; 10&#34;只有一次,对于正在执行的相同代码,我提供以下(编译器依赖但可能是常见的)解释:
<<
重复一下你自己和一些评论说:
离开函数后使用堆栈是 evil 。
答案 2 :(得分:2)
未定义的行为,这意味着一切皆有可能。真正发生的事情取决于编译器的实现。
答案 3 :(得分:1)
我认为即使func()执行完成,localnum的值仍将被保持并且不会被销毁,直到任何进程使用内存空间(但设置一些位/标志,以便剩余的进程将此内存块视为空闲和可以使用它) - 如果我错了,请纠正我
因为这是一个UB,所以你并不完全正确。有些编译器可能会设置一个位/标志,而其他一些编译器可能会将该值设置为零......因为UB为每个编译器提供了自由行动,你的解释只是其中之一(尽管我认为它是最常见的一个)
我的问题是,我没有在这些版画之间运行任何过程,但价值仍在变化。这意味着我的系统中的任何其他进程都在这些打印之间使用了localnum的内存区域?
如果您的流程没有执行,并且值已更改,那么,是的,其他人正在更改该值。请注意,即使您没有直接更改该地址中的值,您的代码也可能以一种在背后更改它的方式实现(例如,&lt;&lt;运算符,如Yunnosch所说)
在这里,我返回一个局部变量作为参考(实际上我不应该这样做,但我只是为了学习行为而这样做。)
我不建议学习UB案例中的行为。它因机器而异。
答案 4 :(得分:0)
因为int localnum 的范围是func函数,所以实际上是在函数返回后返回对不再可用的东西的引用