2016-10-22 39 views
2
#include <iostream> 
using namespace std; 

class V3 { 
public: 
    double x, y, z; 
    V3(double a, double b, double c) { 
     x=a; 
     y=b; 
     z=c; 
     cout << "Addresses are " << &x << " " << &y << " " << &z << endl; 
    } 
}; 

int main() { 
    V3 a(1,1,1), b(2,2,2), c(3,3,3), d(4,4,4); 
    cout << sizeof(a) << " " << sizeof(b) << " " << sizeof(c) << " " << sizeof(d) << endl; 
} 

在上面提到的代码中,我试图看看C++如何在内存中存储对象。在运行这段代码,我得到下面的输出 -我尝试制作对象时跳过了8个字节?

Addresses are 0x7ffc5996b160 0x7ffc5996b168 0x7ffc5996b170 
Addresses are 0x7ffc5996b180 0x7ffc5996b188 0x7ffc5996b190 
Addresses are 0x7ffc5996b1a0 0x7ffc5996b1a8 0x7ffc5996b1b0 
Addresses are 0x7ffc5996b1c0 0x7ffc5996b1c8 0x7ffc5996b1d0 
24 24 24 24 

所以对于对象b,我不知道为什么我没有得到0x7ffc5996b178为我的地址。为什么C++在启动下一个对象之前跳过8个字节?

+0

什么平台(操作系统,编译器,版本)?优化是打开还是关闭? –

+0

g ++(Ubuntu 4.8.4-2ubuntu1〜14.04.3)4.8.4。编译时没有使用额外的标志 – martianwars

+4

第二个构造函数有什么区别吗?如果没有,为什么包括在内? (见MCVE - [MCVE]。)作业是否必要?如果你使用'V3(double a,double b,double c):x(a),y(b),z(c){cout << ...; }'?我不指望有什么区别。你尝试在'main()'中打印类对象的地址吗?这是否会让事情变得轻松?但最终,你的问题是徒劳的 - 编译器允许使用它选择的任何布局和对齐方式,只要它能给出正确的结果。 –

回答

1

将各种评论转换为社区Wiki答案。

  • 是分配必要吗?如果您使用V3(double a, double b, double c) : x(a), y(b), z(c) { cout << …; },有什么变化吗? (我不希望有任何区别。)你是否尝试在main()中打印类对象的地址?这是否会让事情变得轻松?但最终,你的问题是徒劳的 - 编译器允许使用它选择的任何布局和对齐方式,只要它能给出正确的结果。

  • 只是猜测:x86缓存行是64字节。通过这种方式对齐,前2个对象可以放入1个缓存行,第三个放入第二个缓存行。如果它们不以这种方式对齐,则第三个对象将被分割成2个缓存行,这是不好的。正如已经说过的那样,它不一定是明确的。

  • 如果在arch上使用clang进行编译,则在使用g++时,对象密集存储在内存中,但它们不是。