我有以下数据结构:
struct Inner
{
int myValue;
};
struct Outer
{
Inner* inner;
};
选项1
如果我执行以下操作:
Outer outer;
outer.inner = NULL;
outer.inner = new inner;
inner* pInner = outer.inner;
然后为以下2个值添加监视:
然后它们都是非NULL,并且值相等。
选项2
如果我执行以下操作:
Outer outer;
outer.inner = NULL;
inner* pInner = outer.inner;
if (! pInner)
{
pInner = new inner;
}
然后pInner指向有效的堆内存,而outer.inner仍为NULL。
问题的
为什么选项不同 - 它们是否也应该同时指向选项2中的相同内存?
假设我使用选项1,然后我从内部读取值。然后我可以互换使用pInner和outer.inner不能吗?为什么分配内存会有所不同?
答案 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;
}
在此代码中,您不希望pInner
与outer.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
相同的整数值。