class A{};
void Foo(A *p)
{
std::cout << &p << std::endl;
std::cout << p << std::endl;
}
int main()
{
A *p = new A();
std::cout << &p << std::endl;
std::cout << p << std::endl;
Foo(p);
}
上述程序为p
打印相同的值,但&p
的地址不同。有人可以解释一下原因吗?
答案 0 :(得分:6)
上述程序为“p”打印相同的值
这是因为一个p
是另一个的副本,所以它们都具有相同的值。指针的值是存储对象的内存地址,因此具有相同的值意味着指向同一个对象。
函数参数是传递给函数†的对象的副本。
但“&amp; p”的地址不同。有人可以解释一下原因吗?
这里的每个p
都是一个单独的变量和一个单独的对象††。两个对象同时存在。 C ++标准指定每个当前存在的对象具有唯一的地址†††,因此这里的每个p
必须具有唯一的地址。
一元运算符&
是addressof运算符,它返回存储操作数的内存地址。
†除非该函数参数是参考。在这种情况下,引用绑定到传递的对象。 p
参数不是参考。
††指针本身就是对象。存储指针的内存地址与作为指向对象的内存地址的值的内存地址是分开的。
†††在子对象的情况下有例外,但这些例外与此无关。
答案 1 :(得分:3)
void Foo(A *p)
{
std::cout << &p << std::endl;
std::cout << p << std::endl;
}
当您将某些内容传递给Foo()
时,某些内容会被复制到p
。所以实际参数(传递的内容)与形式参数(p
不同虽然他们将保持相同的价值。
在Foo()
内,&p
将打印此形式参数的地址,而不是传递的实际参数的地址。
由于形式和实际参数保持相同的值,p
打印相同的值。
答案 2 :(得分:1)
运算符&
返回变量地址
它们是差异变量A *a
和Foo(A *a)
,但它们指向相同的地址。它通常有不同的地址。
答案 3 :(得分:1)
这是堆栈和堆的很好的描述。 What and where are the stack and heap?
其他人提到的简短回答是:
指向从堆中分配的已分配A的实例。它是由运营商&#39; new&#39;创建的。在你的代码中。
&amp; p指向p本身占用的内存。 就像A类占用内存(使用&#39; new&#39;运算符从堆中分配)一样,p占用内存(从堆栈分配,因为它是局部变量)。
答案 4 :(得分:1)
由于复制构造函数而发生此事件。
复制构造函数是一个构造函数,它通过使用先前创建的同一类的对象初始化它来创建对象。复制构造函数用于 -
- 从同一类型的另一个对象中初始化一个对象。
- 复制一个对象,将其作为参数传递给函数。(这是指您的问题)
复制一个对象以从函数返回它。
p是包含堆中对象地址的局部变量。和&amp; p是堆栈中p的地址。当我们将p传递给Foo()因为复制构造函数 编译器将p复制到新的局部变量,因此我们有2个指针,它们都指向堆内存中的相同位置。在它们上面是原始p(实际参数),第二个是由复制构造函数构建的Foo()方法中未命名的局部变量(形式参数)。
你也可以在下面的图片中看到p和&amp; p之间的区别。