堆指针分配之间的差异

时间:2009-08-18 01:48:32

标签: c++ pointers heap

我有以下数据结构:

struct Inner
{
    int myValue;
};

struct Outer
{
    Inner* inner;
};

选项1

如果我执行以下操作:

Outer outer;
outer.inner = NULL;

outer.inner = new inner;
inner* pInner = outer.inner;

然后为以下2个值添加监视:

  • outer.inner
  • 平纳

然后它们都是非NULL,并且值相等。

选项2

如果我执行以下操作:

Outer outer;
outer.inner = NULL;

inner* pInner = outer.inner;
if (! pInner)
{
    pInner = new inner;
}

然后pInner指向有效的堆内存,而outer.inner仍为NULL。

问题

  1. 为什么选项不同 - 它们是否也应该同时指向选项2中的相同内存?

  2. 假设我使用选项1,然后我从内部读取值。然后我可以互换使用pInner和outer.inner不能吗?为什么分配内存会有所不同?

4 个答案:

答案 0 :(得分:6)

指针存储内存地址。在第一个选项中,存储new inner中由outer.inner分配的对象的内存位置。然后将该值复制到pInner,两个变量都包含相同的地址。

在第二个选项中,第一个outer.inner设置为包含地址NULL。此值将复制到pInner,两个变量都包含NULL。之后pInner被更改为包含新分配对象的地址,但outer.inner中存储的地址不受此影响。该地址仍为NULL

指针只是恰好是内存地址的数字。不同的赋值与变量声明为int时的工作方式相同。事实上,当*->用于取消引用指针时,这些数字实际上是内存地址。两个不同的指针变量可能指向相同的地址,但它们仍然是不同的变量。

答案 1 :(得分:1)

在C ++中,任何赋值a = b(或复制构造函数<<sometypehere>> a = b)通常将位从b复制到a用于普通的旧数据类型(您可以覆盖operator=并复制构造函数以获得不同的效果,但这显然不是这里的情况,因为类型是指针;-)。因此,如果稍后修改b,那对a完全没有影响,它只保留赋值或复制构造函数复制到它的完全相同的位。

Re 2,只要两个指针完全相同(你从另一个指定了一个并且在分配后没有改变它们中的任何一个)那么当然你可以无差别地使用它们进行访问(是写作或通读它)。的分配 (和复制)是完全和非常不同的(事实是 assigment或copy是指向新分配的内存的指针,是一个红色的鲱鱼)。

答案 2 :(得分:1)

Outer outer;
outer.inner = NULL;

Inner* pInner = outer.inner;
if (! pInner)
{
    pInner = new Inner;
}

为什么在将new Inner分配给pInner之后,期望outer.inner改变?他们是独立的。

你需要让pInner成为对outer.inner的引用:

Inner*& pInner = outer.inner;

然后选项2就像你想要的那样工作。


P.S。标识符不应仅仅基于大小写,这容易出错。一个很好的例子:“新内在”和“内在* pInner”

答案 3 :(得分:0)

假设代替指针,我们正在谈论整数。指针只是容器,其值是内存地址,无论如何都是简单的数字。请考虑以下代码,

struct Inner {
  int myValue;
}

struct Outer {
  int inner;
}

Outer outer;
outer.inner = 0;

int pInner = outer.inner;

if(!pInner) {
  Inner inner;
  pInner = &inner;
}

在此代码中,您不希望pInnerouter.inner具有相同的值吗?


也许有点愚蠢:指针只是一个值,就像任何int一样。在给出这些知识的情况下,让我们解构你的榜样:

Outer outer;
outer.inner = NULL;

就在这里,outer.inner == 0是真的。您已将0分配给outer.inner

inner* pInner = outer.inner;

现在,您已将值0复制到pInner,因此也pInner == 0。请注意,一个内存地址,该地址的数据。在这种情况下,内存地址为0x00000000

if (! pInner)

评估为true,因为pInner == 0

{
    pInner = new Inner;
}

现在,pInner被分配了一个由系统生成的新整数。 pInner不再具有与inner.outer相同的整数值。