C++基础知识三

一.引用

 1.变量名

1.1变量名实质上是一段连续存储的空间的别名,类似于门牌号,程序中通过变量来申请并命名内存空间

  1.2通过变量名来使用存储空间,那一段连续的内存空间是否可以有一个别名?

2.c++引用概念

引用可以看作一个已定义的变量的别名,语法:type &name = var

#include <stdio.h>
 
int main()
{
    // 定义一个int型变量a,在内存中占4个字节,
    // 变量名 a 就代表了这一块内存,或者说 a 是这块内存的别名
    int a = 10;
 
    // 定义了一个引用变量 b ,它是 a 的别名,和 a 代表同一块内存空间
    // 对 b 的操作 和 对 a 的操作是一样的
    int& b = a;
 
    // 改变 b 等于改变了 a
    b = 20;
 
    printf ("%d, %d\n", a, b);
 
    // a 与 b 代表同一块内存空间
    printf ("%p, %p\n", &a, &b);
 
    return 0;
}

注:普通引用在定义时必须用其他变量进行初始化,引用是一块空间的别名,若空间不存在,引用就没有意义

3.引用作为其它变量的别名而存在,因此在一些场合可以代替指针

#include <stdio.h>
 
void swap1 (int &a, int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}
 
void swap2 (int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
 
int main()
{
    int a = 10;
    int b = 20;
 
    swap2 (&a, &b);
    swap1 (a, b);
    printf ("%d, %d\n", a, b);
 
    return 0;
}

4.复杂数据类型的传递

#include <stdio.h>
 
struct Student
{
    char name[20];
    int age;
};
 
void printS1(Student *pS)
{
    printf ("%s , %d\n", pS->name, pS->age);
}
 
// 复杂数据类型的引用
void printS2(Student &pS)
{
    printf ("%s\n", pS.name);
    pS.age = 80;
}
 
void printS3(Student pS)
{
    printf ("%s , %d\n", pS.name,pS->age);
}
 
int main()
{
    Student stu = {"xiaoming", 2};
 
    printS1(&stu);  // 地址传递,pS 是 变量 stu 的指针,引用成员要用 ->
 
    printS2(stu);   // pS 是 stu 的别名,和 stu 代表的是同一块内存空间,使用成员和 stu 一样 用.
    printf ("%d\n", stu.age);
 
    printS3(stu);   // 值传递,pS 是 stu 的一份复制
 
    return 0;
}

5.引用类型是否占内存空间?

struct stu2
{
	char &a;
	char &b;
};

int main()
{
	//C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同
	printf("%d\n",sizeof(stu2));  // 8

	return 0;
}
引用的本质:

  引用在C++内部实现是一个常指针,type &name ==>  type *const name

C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。

#include <stdio.h>
 
int main()
{
    int a = 10;
    int &b = a;  // int * const b = &a;
 
    // *b = 20;
    b = 20;
 
    // printf ("%p, %p\n", &a, &(*b));
    printf ("%p, %p\n", &a, &b);
 
    return 0;
} 

void func(int &a)
{
    a = 20;
}
在编译器内部被转化为什么形式?
void func(int *const a)
{
    *a = 20;
}
6.函数返回值作为引用,定义函数时在函数名前加 &

#include <stdio.h>
#include <iostream>

using namespace std;

//函数返回值作引用,定义函数时在函数名前加&
int &fun8()
{
	static int a = 1;
	a++;

	printf("a = %d\n",a);

	return a;
}

int main7_1()
{
	//函数返回值时引用,用引用接,接回来的是一个引用
	int &b = fun8();  //用引用接函数返回的引用  a = 2
	b = 100;
	printf("b = %d\n",b);  //b = 100
	fun8();  //a = 101

	int c = fun8();    //a = 102  用普通变量接函数返回值,接到的是一个值
	printf("c = %d\n",c);  //c = 102
	c = 200;
	fun8();  //a = 103

	fun8() = 300; // a= 104  函数作为左值使用
	printf("b = %d\n",b); //b = 300
	fun8(); //b = 301

	return 0;
}

函数返回值是引用,不能返回栈上的引用,可以返回静态变量和全局变量

//定义一个全局变量 p 
int p;
int func1(int r)  //以返回值的形式返回函数值
{
	p = r++;
	printf("p = %d\n", p);

	return p;
}

int& func2(int r)  //以引用形式返回函数值
{
	p = r++;
	printf("p = %d\n", p);

	return p;
}

int &func3()
{
	static int k = 10;  //定义一个静态局部变量
	k++;
	printf("k = %d\n", k);

	return k;
}
int main()
{
	int a = func1(10);
	int &b = func2(10);

	printf("a = %d,b = %d\n",a, b);

	int &c = func3(); //k = 11
	printf("c = %d\n", c);  //用引用接函数返回值 c = 11

	c = 100;
	printf("c = %d\n", c); // c = 100
	func3();  // k = 101

	//函数作为左值使用
	func3() = 200;  // k = 102
	func3();   // k = 201

	return 0;
}

6.1常引用

int main()
{
	const int a = 10;
	int c = 100;

	//int &b = c;  普通引用

	const int &b = c;
	b = 200;

	return 0;
}


常引用不能通过引用改变被引用的值。

6.2常引用初始化

int main()
{
	//1. 用变量初始化
	int pa = 10;
	const int &pb = pa;  

	printf("pb = %d\n", pb);  // pb = 10

	//2. 用常量初始化
	{  //const int *const pb
		const int &pb = 100;
		int *p = (int *)&pb;
		*p = 200;
		printf("pb = %d\n", pb);  //pb = 200
	}

	return 0;
}
注:用常量进行初始化时,编译器会为常量分配一块空间,将常量的值复制到这个空间里,然后常引用作为这个空间的别名。


如有欠缺或不足请留言,谢谢!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值