指针和引用详解---基础篇

(153) 2024-03-16 07:01:01

指针

  1. C++每个变量都有一个内存位置,每个内存位置都定义了一个可用&访问的地址,表示在内存中的一个地址,&a表示变量a的地址
  2. 指针本身是一个对象(是一个变量),他的值是另一个变量的地址,指向一块内存,指针存的是指向一块内存的地址。指针分配内存空间,允许对指针的赋值和拷贝,指针在定义的时候不需要初始化(建议初始化)
int a = 20;//声明一个实际变量
int *p;//声明一个指针变量
p = &a;//把变量的地址赋给指针,就是在指针变量中存储a的地址
cout << p << endl;//输出指针变量中存储的地址
cout << *p << endl;//访问指针变量中地址指向的值,这里就是20

给指针赋NULL是一个良好的编程习惯,int *a = NULL

  1. p++指针的递增是指向下一个内存的位置,如果是int型下一个就是移动4个位置,如果是char型,下一个就是移动1个,
  2. 多级间接寻址,指向指针的指针,**
  3. 指向数组的指针,数组a[],*(a+4)是一个访问a[4]的合法方式
  4. sizeof指针”得到的是指针本身的大小,而”sizeof引用”得到的是所指向的变量的大小
  5. 32位系统的指针是4字节,64位的是8字节

引用

  1. 引用是给已经存在的对象起了一个小名(也就是跟原来的对象就是一个东西),必须被初始化,定义引用的时候,就是将引用和初始值绑定在一起,一直绑定,而不是拷贝给引用,所以对引用的操作都是在绑定的对象上进行的,(引用本身不是对象,所以引用不能再被引用了),所以引用在初始化后就不能再被改变了,指针可以改变,可以先后指向不同的对象
  2. 因为引用不是新创建的对象,所以引用不分配存储空间,指针如果初始化需要分配存储空间
  3. 引用与指针的区别,指针的值可以为空,但是引用的值不能为NULL,不存在空引用;一旦被初始化为一个对象就不能指向另一个;引用必须在创建时被初始化
  4. 引用使用时无需解引用,指针需解引用
  5. 引用可以作为参数传递,是实参的小名,如果不改变变量的值,通常采用常引用传参
  6. 对引用自增自减是引用代表的对象的值发生变化,对指针自增自减是指针指向的位置发生变化
    赋值永远改变的是等号左侧的对象
int i = 42;
int &r = i;//r是一个引用,是i的小名
int *p;//p是一个指针
int *p1 = nullptr;//定义p1是一个空指针
int *p2 = &i;//这里的&在等号右边是取地址符,指针p2存放的是i的地址
*p2 = 0;//这里的*是解引用符号,得到指针p2所指的对象,也就是经p2给i赋值,解引用操作仅适用于指向了某个对象的有效指针
p1 = &adc;//p1的值被改变,现在pi指向adc
*p1 = 0//*p1被改变,也就是指针pi指向的那个对象发生改变

函数引用传参
引用和原始变量都指向同一个地址,因此通过引用修改原始变量中存储的变量值,修改引用就是修改原始值;所以可以用于函数传递参数或函数返回值

函数引用传参,将函数的形参指定为引用,调用时就是把实参直接传递给形参,而不是拷贝给形参,所以在函数体中修改了形参,实参也会被修改
(补充一点:值传递只是简单的拷贝,不会实现交换两数的目的,因为传进去的是实参放的副本(副本啥意思,就是把实参的值拷贝一份然后传进去),在交换函数内部执行的是形参的改变,形参的改变不会影响原来的实参)

swap(num1, num2);//引用传递
void swap(int &a, int &b){ 
   
    int temp = a;
    a = b;
    b = temp;}
//这种方式也是可以的,下面这个传的是地址
swap(&num1, &num2);
void swap(int *a, int *b){ 
   
    int temp = *a;//这里尽量不要把temp作为指针,因为没有初始化很危险,当然你初始化了就是可以
    *a = *b;
    *b = temp;}

此文关于各种传递比较正确https://www.cnblogs.com/chen-kh/p/6696305.html
常引用:不希望通过引用来修改原始变量的值
const int &b = a;

纸上得来终觉浅,绝知此事要躬行,指针总是指来指去,还是上机看下到底怎么指

#include <iostream>
using namespace std;

int main()
{ 
   
	int a[5] = { 
   1,3,4,6,5};
	int *p = a;
	cout << p<<endl;//结果为0x7ffeefbffde0
	cout <<*p<<endl;//结果为1,因为数组名a相当于数组的第一个元素
	p++;
	cout << p<<endl;//结果为0x7ffeefbffde4,注意比刚刚的增加4,因为一个int 是4,地址虽然执行的是+1,实际是+4
	cout << *p<<endl;//结果为3,,自然就是第二个元素,因为地址变了
	*p++;//执行完这个语句,*p向下指一位
	cout << p<<endl;//所以结果为0x7ffeefbffde8,地址又增加了4
	cout << *p<<endl;//结果为4,指向的内容自然随着地址变化
	(*p)++;
	cout << p<<endl;//结果为0x7ffeefbffde8。地址没变,加的只是指向对象的值
	cout << *p<<endl;//结果为5,这里是刚刚的4+1
	*(p++);
	cout << p<<endl;//结果为0x7ffeefbffdec,地址又增加了
	cout << *p<<endl;//结果为6,指向的内容变化了
   return 0;
}

我想通过博客帮助和我一样有困惑的小伙伴,看完此文你懂了吗,欢迎一起交流,博客仅为我个人的学习笔记,如有错误,欢迎指正

THE END

发表回复