"类实例化对象的内存地址和对象地址内的变量"在C ++中

时间:2017-04-20 12:56:01

标签: c++ memory-address

我正在努力理解内存寻址在主程序中声明的变量与实例化类对象内的变量之间差异的概念!

我的问题是当我宣布两个变量时,例如" int a,int b"在主程序内部,它需要4 + 4个字节,特定的两个地址在内存中的某个位置。例子" a在内存0x248444中,b在0x248448" ....在这种情况下很好....

当涉及具有两个变量" int c,int d"的类实例化对象时,该对象采用8字节的内存地址示例" 0x248544",该地址如何? " int c和int d" ?

因此int c和int d的地址在该对象地址内#34; 0x248544" ? int c和int d是否有特定的地址?

如何理解实例化的类对象地址与该对象内变量的地址有什么区别?

希望我的问题很明确......

在互联网上搜索后,我在C ++对象模型中发现了一本名为"的书#34;但是对于在实例化的类对象中声明的变量和在main中声明的变量的内存差异的基本理解。有人请帮助我说清楚。

先谢谢。

2 个答案:

答案 0 :(得分:2)

好的,你有一个像这样的C类:

class C
{
   int c;
   int d;
};

类C(C c)的实例将占用一些内存,它需要(提供的int大4个字节 - 但不一定是所有机器上的情况)8个字节。

如果一个实例位于地址0x248544,它将完全占用该地址的字节+下一个后续的字节。在如上所述的这样一个简单的类中,没有任何其他条件,c将占用这八个字节中的前四个,d接下来的四个字节。

因此c.c与您的对象c具有完全相同的地址,c.d之后位于四个字节,因此地址为0x248548。

请注意,第一个成员不一定与您的对象具有相同的地址!让我们修改我们的C类:

class C
{
   virtual ~C() { } // virtual destructor -> C gets virtual!
   int c;
   int d;
};

现在,sizeof(C)将为16(!)(提供的指针需要8个字节的存储空间,就像现代的64位硬件一样)。为什么?该类获取一个指向vtable的附加指针,该表通常是C类的第一个(但不可见)成员。

所以c仍然在地址0x248544,但现在指向vtable的(不可见)指针共享该地址;之后是c.c,因此位于地址0x2484c,而c.d则位于0x24850。

在这方面,C ++与C不同,其中struct的第一个成员总是共享结构本身的地址......

然而,在C和C ++中,两个后续成员不一定必须触摸"彼此之间可能会填充一些字节 - 关键字字节对齐。

此外,C ++允许重新排序类的成员: 如果在C中,如果在a之前声明了结构成员b,那么a必须放在内存中b的前面,这只是在C ++中只需要具有相同可访问性的成员!

class C
{
    int a;
public:
    int b;
private:
    int c;
};

现在允许编译器保持原样,但也可以将b放在其他两个之前或之后 - a之后不允许放置c $cart->addProduct($product, array( 'selected_configurable_option' => NULL, 'related_product' => NULL, 'qty' => $qty )); }}

长篇小说,简短的结论:所有这些内存布局都比你想象的要复杂得多......

对vtable的旁注:vtable指针不需要在那里(就C ++标准而言) - 如果任何编译器供应商找到更好的解决方案来实现多态,他们可以自由地这样做 - if < / em>他们发现......但是vtable是当前最先进的技术,是事实上的标准。

答案 1 :(得分:1)

您可以将类实例视为其成员变量的包络。类实例的大小是其成员变量的大小加上它们之间的可选填充。通常(继承和多态可能会弄乱这个)第一个成员变量的地址与类实例的地址相同。您可以获取成员的地址并在调试器中调查它们以查看其工作原理。 E.g。

class C
{
public:
    int a = 1;
    int b = 2;
};

C c;
int* p_a = &c.a;
int* p_b = &c.b;

检查c占用的内存,您会在里面看到值12

保留成员变量的顺序,并且由于填充,可能会影响类实例的大小。

空类的实例必须具有地址,因此其大小永远不会为0.

会员功能是另一回事。虽然它们也位于内存中,但它们由所有实例共享,因此存储在一个地方,与实例分开。