这个问题之前和同学交流过,一时之间没有记录下来,前两天在刷 Leetcode 350. Intersection of Two Arrays II 时又遇到一次,这次要解决掉这个问题。
示例一
我们先看看能重现这个问题的最简短的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream> using namespace std; int main() { for (int i = 0; i < 3; i++) { int a = i; cout << &a << endl; } }
|
虽然每次执行程序输出的地址都不相同,但三个地址总是相同。为什么会这样?
查看 stackoverflow 这篇问答和这篇问答后,了解到这是编译器的优化,因为 a 在完成循环里的一次迭代后,作用域失效,在下一次迭代时又要创建 int 型数据,所以直接重用了该地址,不再另外分配内存地址。也可以理解为销毁了 a 所在内存地址的数据,在下次迭代时,又分配到那个地址。
示例二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(0); v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); for (int i : v) { cout << " i: " << &i << " " << i << endl; static int j = 0; cout << "v[" << j << "]: " << &v[j] << " " << v[j] << endl << endl; j++; } }
|
示例二的 int i,跟示例一的 int a 很像,我猜想 for (int i : v) 的语法背后就是用示例一的做法实现的。那么我们只要把 for (int i : v) 改为 for (int& i : v),结果就一样了(即对于 v 里的每个 int 型数据,通过引用 i 操作):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(0); v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); for (int& i : v) { cout << " i: " << &i << " " << i << endl; static int j = 0; cout << "v[" << j << "]: " << &v[j] << " " << v[j] << endl << endl; j++; } }
|
示例三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <iostream> #include <vector> using namespace std; void foo() { int x = 1; cout << "x: " << &x << " " << x << endl; } int main() { for (int i = 0; i < 3; i++) { foo(); } }
|
为什么三次调用 foo,三次的 x 内存地址都是相同的?
我们再看看示例四。
示例四
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <iostream> #include <vector> using namespace std; void foo2(int val) { int y = val; cout << "y: " << &y << " " << y << endl; } void foo3(int val) { int z = val; cout << "z: " << &z << " " << z << endl; } int main() { foo2(7); foo3(11); }
|
为什么调用不同的函数 foo2, foo3,各自不同的局部变量 y, z 的地址也一样?
详见 stackoverflow 这篇问答。
相关资料:《C++ 变量存储方式》