指针的本质
指针实际上就是一个整数,存储着一个内存地址。
不必执着于用“类型”的概念区分,那只是为了方便设计出来的,所有的指针,本质上都是一个整数,存储着一个内存的地址。
#include <iostream>
#define LOG(x) std::cout << x << std::endl
int main()
{
int var = 8;
void* ptr = &var;
std::cin.get();
}
当在类型后加*时,意味着这个变量是个指针,当在变量前加&时,表示在问这个变量:“你的地址是啥?”。
在定义指针变量这行打上断点,运行后发现指针变量的确存储一个数,在内存视图进入这个数表示地址,可以看到里面存储着8。
当改变指针类型为int
,可以发现做的事情并没有变。给指针定义类型,只是告诉我们这里住着什么样的数据,它是帮助我们操作内存的工具,仅此而已。
将指针类型改为void
,此时访问从指针的角度访问变量var
,即通过门牌号去敲门。此时编译器报错,因为指针的类型是void
,这会使编译器不知道要操作多大的内存空间。
另外,指针本身也是存储在内存里的变量,这意味的指针同样存在指针,可以定义指针的指针的指针。。。
但指针的本质不变,它只是一个整型,存储着一个内存的地址。
引用,reference
从本质上来讲,指针与引用是一回事,引用是指针的语法糖,可以使代码更易读。
区别在于,指针可以定义为指向空,而引用必须是已经存在的变量,引用不真正占用内存,并不像之前的那些类型那样存储数据。
#include <iostream>
#define LOG(x) std::cout << x << std::endl
int main()
{
int a = 8;
int& ref = a;
std::cin.get();
}
在这段代码中,int&
表示创建了一个引用,这也意味着给a起了一个别名(alias) 。
现在创建一个函数,让输入的值递增
void Increment(int value)
{
value++;
}
如果此时调用函数:Increment(a)
,然后查看a的值,会发现它并没有增加,因为此时做的事传值调用(passing by value),也就是说只是在函数内定义了一个等于5的value
变量,而并非对a进行操作。所以,不妨直接传入a的地址,让函数读取a的内存地址,这样就可以直接对a进行操作了。
void Increment(int* value)
{
*value++;
}
将函数改成这样,调用需要写成Increment(&a)
,*value
代表逆向引用,表示改变的是该地址下的值,而不是表示地址的数本身。 但这样写有些复杂,符号太多,所以可以用引用的形式,做引用传递。
void Increment(int& value)
{
value++;
}
将函数的形参改为引用的形式,调用时也可简化为Increment(a)
,代码做的事其实一模一样,但是具有了更好的可读性。
另外,在使用引用时,必须在声明的时候就进行赋值,在这之后,想要改变引用指向的对象是做不到的。
教程来源:The Cherno C++ 教程
标签:变量,笔记,C++,内存,value,引用,Increment,指针 From: https://blog.csdn.net/m0_59669215/article/details/139708928