指针和引用

1. 指针:

指针是一个变量(对象),它的内容是一个地址,指向内存的一个存储单元。通过修饰符“*”来表示,解引用 *p 来表示指针p所指对象的值。指针在逻辑上是独立的,可以改变,比如指针变量的值和指针变量指向的内存的值都是可以改变。不同类型的指针可以指向特定类型的对象,即指针的类型要与所指向的对象的类型一致。可通过指针的指向来改变所指向的对象的值。

const指针:
  1. 常量指针
const int *p;
int a = 20;
int b = 30;
p = &a;

p为常量指针,常量指针不一定要指向常量,既可以指向常量也可以指向变量,常量指针的含义是不能通过p(常量指针)来改变所指向对象的值。但是并不代表不能通过其他的途径来改变对象的值。

要点:

  • 常量指针不允许通过自身来改变对象的值
  • 常量指针指向的地址可以改变

例如:

const int *p;
int a = 10;
int b = 20;
p = &a;
*p = 60; 错误//不能通过常量指针p来修改对象a的值

 int *p2 = &a;
*p2 = 40;  //通过p2修改了a的值,进而p1指向的内容也修改了

p = &b;  //p开始指向a的地址,现在让p指向b的地址

        2.指针常量

int a = 10;
int* const p = &a;
p为指针常量,p所指向的地址不可改变,即 p只能初始化,不能改变p所指向的对象,但是对象的值可以通过p来改变。


2. 引用:

引用是一个变量的别名,用“&”来修饰,此处的“&”并不是取地址符,而是代表复合类型。引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个名字,引用变量指向的是原变量在内存中的地址。引用在逻辑上是不独立的,它的存在具有依附性,所以一开始就得进行初始化,并且在整个生命周期中不能被改变,“从一而终”,可以通过引用来改变变量的值。

//指针和引用
int main()
{
    int a = 10;
    int c = 20;
    int *p = &a; //p指向a在内存中的地址,p是一个独立的变量
    int &b = a;  //b是a的别名,b指向a在内存中的地址,b依附于a而存在
    int &d = c;

    printf("变量 a=%d, %p\n", a, &a);
    printf("引用变量 b=%d, %p\n", b, &b);
    printf("变量 c=%d, %p\n", c, &c);
    printf("引用变量 d=%d, %p\n", d, &d);
    printf("指针变量 p=%d, %p\n\n", *p, p);

    c = *p;  //将p所指向的内存的内容赋给a
    printf("c=%d, %p\n", c, &c);
    printf("指针变量 p=%d, %p\n\n", *p, p);


    *p = 30; //将p所指向的内存的内容重新赋值为30,通过指针来改变变量的值
    printf("a=%d, %p\n", a, &a);
    printf("b=%d, %p\n", b, &b);
    printf("指针变量 p=%d, %p\n\n", *p, p);


    b = 50;   //b是a的别名,对b进行修改,就是对a进行修改
    d = a;   //d是c的别名,不能将一个变量赋给引用变量
    

    printf("a=%d, %p\n", a, &a);
    printf("b=%d, %p\n", b, &b);
    printf("c=%d, %p\n", c, &c);
    printf("d=%d, %p\n", d, &d);
    printf("指针变量 p=%d, %p\n", *p, p);

    return 0;
}



引用的特点:
  • 一个变量可以取多个别名
  • 引用必须初始化
  • 引用只能在初始化的时候引用一次,以后不能再绑定其他的变量
  • 引用只能绑定在对象(变量)上,不能与表达式的结果或字面值绑定在一起,例如:int &a = 10; 是错误的
const引用(常引用):

const引用是指----指向“常量”的引用,其实这里的“常量”和常量指针的含义是一样的,const引用可以和常量绑定,也可以和变量绑定,只是不能通过const引用来改变绑定对象的值

非const引用不能与const对象绑定。因为常量a(const对象)的值不可改变,但却可以通过非const引用来改变常量a(const对象)的值,这是不正确的。

const int a = 10;
int &b = a; //错误,非const引用不能与const对象绑定
b = 20;  //这是不正确的
const引用和非const引用的区别:
  • const引用只读不可修改,与绑定对象是否为const无关。

  • 非const引用可读可改,只能和非const对象对象绑定
  • 非const引用只能绑定到与该引用同类型的对象,const引用则可以绑定到不同但相关的类型的对象
  • const引用可以初始化为不同类型的对象或者初始化为右值,如字面值常量

example:

int main()
{
	int a = 10;
	int &a1 = a;  //非const引用
	cout<<"a1= "<<a1<<endl;

	const int &a3 = 10; //初始化为右值
	cout<<"a3= "<<a3<<endl;

	const int &a4 = a+10; //初始化为右值
	cout<<"a4= "<<a4<<endl;

	double d = 1.20;
	const int &a5 = d; //初始化为不同但相关的类型
	cout<<"a5= "<<a5<<endl;

	return 0;
}

注意:

  • 如果是对一个常量进行引用,则编译器首先会建立一个临时变量,然后将该常量的值置入临时变量中,对该引用的操作就是对该临时变量的操作。
  • const引用表示,试图通过引用去改变其引用的对象的值时,编译器会报错。但这并不意味着,此引用所引用的对象也因此变成const类型了。我们仍然可以改变其指向对象的值,只是不通过引用。
int main()
{
	int a = 10;
	const int &b = a;
	//b = 20; //出错

	a = 20;  //通过a间接的修改了const引用b的值
	cout<<"b= "<<b<<endl;

	return 0;
}


const引用并不是说不可以修改,只不过不能通过const引用来修改,但可以通过其所引用的变量来间接修改const引用变量,这里说的const只是对程序员的一种约束,不要试图去修改const引用修饰的变量。

3. 指针和引用的区别:

  • 引用只能在定义的时候初始化一次,之后不能改变其指向,从一而终;指针变量的指向可以改变。
  • 引用必须指向有效的变量;但是指针可以为空。
  • sizeof 指针对象和引用对象的意义不一样。sizeof引用得到的是所指向的变量的大小;而sizeof指针是对象地址的大小。
  • 指针和引用自增(++)和自减(--)。
  • 相对而言,引用比指针更安全。指针比引用更灵活,但是也更危险。使用指针时一定要注意检查指针是否为空。指针所指的地址释放以后最好置NULL,否则可能存在野指针的问题

野指针:指针所指向的地址不能进行操作,即指向一个没有访问权的内存区。

产生原因:

  • 指针变量定义的时候未初始化。指针变量在创建的时候应当被初始化为NULL,或者让它指向一个合法地址。如果没有进行初始化,它的缺省值是随机的,指向一个不知道的内存空间。
  • 指针释放之后未置空。指针使用free或delete释放之后,只是切断了指针和内存块之间的指向关系,并没有把指针本身干掉。指针指向的就是未知内存,在后面使用这个指针的时候,它的值是随机的,有可能会造成意想不到的后果。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值