概述
以前学习C++内存模型 时就有提到,栈内存地址是从高到低的。最近查找资料(面向百度/谷歌编程)时又看到了这点,于是心血来潮想验证一下。
验证
编写一段简单的代码:
class A {
public:
A() {}
A(const string& str) { cout << str << "\n"; }
int a = 1;
};
class B : public A {
public:
B() {}
B(const string& str) : A(str) {}
int b = 1;
};
class C : public B {
public:
C() {}
C(const string& str) : B(str) {}
int c = 1;
};
int main() {
A a;
B b;
C c;
A* v1 = &a;
B* v2 = &b;
C* v3 = &c;
int s1 = sizeof(A);
int s2 = sizeof(B);
int s3 = sizeof(C);
cout << "a.address=" << v1 << "\n";
cout << "b.address=" << v2 << "\n";
cout << "c.address=" << v3 << "\n";
cout << "A.size=" << s1 << "\n";
cout << "B.size=" << s2 << "\n";
cout << "C.size=" << s3 << "\n";
return 0;
}
上述代码依次在栈中创建对象a、b、c并输出地址和大小。
在VS2019的Debug模式下运行:
可以看到,对象a、b、c地址依次递减,符合预期。
在Release下运行:
Release下结果却与预期完全相反,地址依次递增,并且无论如何改变a、b、c的声明顺序,a、b、c的地址都是依次递增。
注意到,从代码逻辑上看,这3个对象的声明顺序其实并不严格,那么修改逻辑:
...
int main() {
A a("create a");
B b("create b");
C c("create c");
//A a;
//B b;
//C c;
...
}
三个对象都会在构造函数中依次输出字符串,此时创建顺序需要严格遵守。
在Release下执行:
对象a、b、c的地址依次递减,符合预期。
显然,这是Release的代码优化导致的,编译器检测到对象a、b、c的创建并不要求先后顺序(从代码逻辑上看),于是将这3个对象按size从大到小的顺序进行创建,即创建顺序变为c、b、a。
关闭代码优化后,运行结果也符合预期。
结论
1.栈内存地址是从高到低的
2.Release的代码优化会导致与Debug执行有所区别。