为何C++非静态函数变量表现类似静态变量?初始化疑问
我为理解C++静态与非静态变量的差异,写了如下代码,通过打印内存地址分析特性:
#include <iostream> void testStatic(int currNum) { static int counter; std::cout << "Address of counter: " << &counter << "\n"; counter += currNum; std::cout << "counter: " << counter << "\n"; } void testNonStatic(int currNum) { int nsCounter; std::cout << "Address of Non-static counter: " << &nsCounter << "\n"; nsCounter += currNum; std::cout << "Non-static counter: " << nsCounter << "\n\n"; } int main() { for(int i = 0; i < 5; i++) { testStatic(i); testNonStatic(i); } }
我知道静态变量仅分配一次内存,地址全程不变,运行结果符合这个特性。但非静态变量nsCounter的地址也保持不变,值还持续累加(预期输出为0、1、2、3、4,实际为0、1、3、6、10),表现得和静态变量类似。请问是不是必须每次调用函数时初始化nsCounter,才能让它符合非静态变量的预期行为?
以下是运行结果:
Address of counter: 0x558b476c9158 counter: 0 Address of Non-static counter: 0x7fff20471894 Non-static counter: 0 Address of counter: 0x558b476c9158 counter: 1 Address of Non-static counter: 0x7fff20471894 Non-static counter: 1 Address of counter: 0x558b476c9158 counter: 3 Address of Non-static counter: 0x7fff20471894 Non-static counter: 3 Address of counter: 0x558b476c9158 counter: 6 Address of Non-static counter: 0x7fff20471894 Non-static counter: 6 Address of counter: 0x558b476c9158 counter: 10 Address of Non-static counter: 0x7fff20471894 Non-static counter: 10
解答
非静态变量地址不变的原因
非静态局部变量属于自动变量,每次进入函数时会在栈上分配空间。你看到地址不变是因为当前调用场景下,函数的栈帧结构固定,每次调用testNonStatic时,栈上分配的位置恰好相同——这是编译器和运行环境的巧合,并非C++标准规定的行为。如果换个调用场景(比如在其他函数中嵌套调用testNonStatic),变量的地址就会发生变化。值累加的本质
你没有初始化nsCounter,自动变量默认是未初始化状态,它的值是栈上的残留垃圾数据。第一次调用时,该内存位置刚好是0,所以0+0=0;第二次调用时,该位置残留的是上次的0,加1变成1;第三次残留1加2变成3,以此类推。这种“累加”只是读取垃圾值后的巧合,属于未定义行为,换个环境运行可能会得到完全不同的结果。如何让非静态变量符合预期
要让nsCounter每次调用都从0开始累加currNum,必须显式初始化变量,比如修改为:
int nsCounter = 0;
这样每次进入函数时,nsCounter都会被初始化为0,再执行nsCounter += currNum,输出就会是你预期的0、1、2、3、4。
内容的提问来源于stack exchange,提问作者code.c.c

