我不明白第*p1=10
行之后会发生什么,*p2
变量会发生什么,最后secondvalue
变量如何得到 20。
#include <iostream>
using namespace std;
int main ()
{
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue;
p2 = &secondvalue;
*p1 = 10;
*p2 = *p1;
p1 = p2;
*p1 = 20;
cout << "firstvalue is " << firstvalue << 'n';
cout << "secondvalue is " << secondvalue << 'n';
return 0;
}
命令输出
firstvalue is 10
secondvalue is 20
我不明白secondvalue
变量是如何获得值 20 的。
如果我们分配*p2=*p1
变量secondvalue
一定不会得到 10?
让我们一步一步地看看:
int firstvalue = 5, secondvalue = 15;
这将初始化两个 4 字节整数。
---------------------------------------
| | |
| firstvalue (5) | secondvalue (15) |
| | |
---------------------------------------
- 初始化 int 指针并设置其值
int * p1, * p2;
p1 = &firstvalue;
p2 = &secondvalue;
P1 现在存储第一值的地址,P2 存储第二值的地址
---------------------------------------
| (*p1) | (*p2) |
| firstvalue (5) | secondvalue (15) |
| | |
---------------------------------------
p1 p2
- 现在您将 10 分配给 *p1。这样做是它修改存储在 p1 中的内存地址处的值:
*p1 = 10;
---------------------------------------
| (*p1) | (*p2) |
| firstvalue (10) | secondvalue (15) |
| ^^ | |
---------------------------------------
p1 p2
- 现在您将
*p1
分配给存储在p2
中的内存地址。*p1
取消引用指针p1
并返回它指向的值。
*p2 = *p1;
---------------------------------------
| (*p1) | (*p2) |
| firstvalue (10) | secondvalue (10) |
| | ^^ |
---------------------------------------
p1 p2
- 现在你更改p1 指向的内存地址。现在 p1 和 p2 指向同一个变量
p1 = p2;
---------------------------------------
| | (*p1) (*p2) |
| firstvalue (10) | secondvalue (10) |
| | |
---------------------------------------
p1 p2
- 最后,修改 p1 存储的内存地址处的值(也是 p2)。
*p1 = 20;
---------------------------------------
| | (*p1) (*p2) |
| firstvalue (10) | secondvalue (20) |
| | ^^ |
---------------------------------------
p1 p2
p1 = p2;
这不会复制指针指向的值,而只是"寻址"p2
指向的值。因此,此时p1
和p2
都指向secondvalue
,并且更改它们中的任何一个都会对secondvalue
如果我们分配 *p2=*p1,秒值变量不能得到 10 吗?
确实如此。如果这是最后的任务,那么会发生什么。但也许你已经注意到,在这个作业之后还有更多的作业:
p1 = p2;
p1
现在指向p2
指向的相同值。p2
指向secondvalue
,所以p1
现在也指向secondvalue
。
*p1 = 20;
p1
指向的值被分配20
。这就是secondvalue
被分配 20 种的方式。
是的,但是当你p1 = p2;
时,p1现在存储对第二个值的引用,并在下面的行中将*p1(这是第二个值)断言为20。
因此,在您的代码流中,第一个值在*p1 = 10;
上分配给 10,第二个值在*p1 = 20;
上分配给 20
所以,指针和引用(和取消引用,天哪!
唉,这就是词汇发挥作用的地方,人们喜欢这种特殊的词汇选择。所以它就在这里,以其所有的荣耀进行了解释。
值
值是存在于内存中某处的东西(如变量,但不一定)。为了有用,我们程序员喜欢给值一个类型和一个名称。
int x = 74;
double pi = 3.141592;
string name = "Hannah";
引用
直接引用是一个别名,另一个名称,如果你愿意,是一个值。
int x = 7; // type:int, name:x, value:7
int& z = x; // z = another name for x
z = 12; // x = 12;
使用别名是我们在正常生活中做的事情。
- 我叫爸爸">爸爸"。
- 爸爸的朋友叫他">比尔"。
- 我的朋友叫他">格里尔先生"。
不同的名称。同一个人。
现在,一些C++纯粹主义者会告诉你,这些只是普通的参考。是的。。。和没有。是的,就C++语言而言。不,就理解事物而言。请记住,在与C++人交谈时,"参考"一词,除非另有形容词,否则总是意味着直接参考或别名。
指针
在C++引入"引用"作为语言抽象的一部分之前,我们有间接引用- 也称为指针。
它是间接的,因为指针本身不是引用。但是,您可以通过使用*
运算符取消引用来从指针的值中获取引用。
该术语有点不稳定(因为它看起来像您正在"取消"引用它),但事实恰恰相反:您正在获取该间接引用(指针值)并有效地将其转换为(未命名的)直接引用,即"指向"(或"引用")值的别名。
int x = 7;
int* px = &x; // type=(pointer to int) name=“px” value=(address of x)
*px = 12; // (direct reference to x) = 12
换句话说,px
是一个指针,间接引用(即地址)x
。
因此,当我们使用*
运算符取消引用px
时,我们将表达式转换为对x
的直接引用——此时我们可以读取或修改x
的值,就像我们手头有x
一样。
我怀疑术语"取消引用"的产生是因为我们"un"间接引用指针值以获得直接引用,但所有创建该术语的人现在都死了,我不知道他们觉得有必要解释它。
你想问什么
因此,取消引用的指针是目标对象的别名。你想知道如果你不取消引用指针会发生什么,这将是:
"如果我们将一个未取消引用的指针分配给另一个未取消引用的指针,会发生什么?">
。未取消引用意味着不取消引用,所以你基本上是在问:
当我们将一个指针分配给另一个指针时会发生什么?
此时的答案应该不足为奇:每当我们将任何变量的值分配给另一个变量时,都会发生同样的事情。
int x = 7;
int* p1 = &x; // p1 now “points to” x
int* p2 = p1; // and now p2 also “points to” x
请记住,指针的值是内存中另一个对象的地址,您可以根据需要复制值。
*p2 = 42; // x = The Answer