栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++引用---纯属娱乐

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++引用---纯属娱乐

        先给大家扯点别的,宾宾和卷天是计信学院的大一新生,有一天,卷天去宾宾宿舍找他玩,发现宾宾在学3D建模,卷天说:“靠北啦,你这个卷宾!”。

        第二天,卷天将这件事告诉了龙龙,龙龙说:“你这个卷天真没礼貌,随便给宾宾起外号,宾宾再卷,能有你卷吗?”

        在这个故事里,针对宾宾有两个称号,一个是他自己的名字,一个是卷天给他起的外号。一般来讲,不管你是喊宾宾还是卷宾,他都会回应你。

        那这个故事跟引用有什么关系呢?没错,引用就是起个外号--------起别名。

一、引用的定义

1.1对单变量进行引用

语法:类型名 &外号 = 原名

示例:

int main()
{
	int binbin = 10;
	int &juanbin = binbin;//给宾宾取一个外号卷宾
	cout << "我们先看两个变量的值是否一样" << endl;
	cout << "binbin=" << binbin << endl;
	cout << "juanbin=" << juanbin << endl;
	cout << "我们再看一下他们的地址是否一样" << endl;
	int* ptr_binbin = &binbin;//这里的&是取址
	int* ptr_juanbin = &juanbin;
	cout << "a=" << ptr_binbin << endl;
	cout << "b=" << ptr_juanbin << endl;
}

         从这里大家就可以看出,这两个变量不管是变量对应的值,还是地址,都是一样的。这说明,他们就是一个东西,这就是宾宾和卷宾之间的关系。

如果你任保持怀疑,那我们再给juanbin赋值看看。

int main()
{
	int binbin = 10;
	int &juanbin = binbin;//给宾宾取一个外号卷宾
	cout << "修改前" << endl;
	cout << "binbin=" << binbin << endl;
	cout << "juanbin=" << juanbin << endl;
	juanbin = 100;
	cout << "修改后" << endl;
	cout << "binbin=" << binbin << endl;
	cout << "juanbin=" << juanbin << endl;

}

 

到此,我们可以说,引用,其实就是起外号。

但是要注意的是:

1.外号的类型名和被引用变量的类型名是一样的。下面这种情况就是错的 

 2.引用必须初始化,例如   int &b;这样就是错的。很好理解,你起一个外号”卷宾“,是给谁起的外号呢?宾宾啊,起外号,要给一个对象起,也就是说”卷宾“是给宾宾起的外号,你只说一个”卷宾“,别人是不知道这是宾宾的外号,同样的,你不初始化,电脑也不知道是谁的外号,所以引用必须要初始化。

3.引用一旦初始化后,就不可以更改了,例如

    int c = 5;
    int a = 10;
    int &b = a;
    int &b = c;

    就是错的,b不能多次初始化

 

也很好理解,”卷宾“已经是宾宾的外号了,如果有一天卷天当着宾宾的面喊龙龙”卷宾“,宾宾肯定不能接受,因为宾宾是纯爱战士!!!!

那又有同学要说了,前面不是把juanbin从10改成100了吗?这只是赋值操作,不是更改引用。

赋值后还是宾宾的外号,不是牛头人。

1.2 对数组进行引用

上代码

int main()
{
	int binbin[10];
	for (int i = 0; i < sizeof(binbin) / sizeof(int); i++)
	{
		binbin[i] = i;//赋值
	}
	int(&juanbin)[10] = binbin;
	cout << "使用外号访问数组元素" << endl;
	for (int i = 0; i < sizeof(juanbin) / sizeof(int); i++)
	{
		cout << juanbin[i] << " ";
	}
	cout << endl;
	//这边我们用指针访问数组
	cout << "使用指针访问数组元素" << endl;
	int* ptr_juanbin = juanbin;//此处是定义一个指针,并将其指向juanbin
	//如果想获取地址,用*ptr_juanbin =& juanbin;
	for (int i = 0; i < sizeof(juanbin) / sizeof(int); i++)
	{
		cout << *ptr_juanbin+ i << " ";
	}
	cout << endl;
}

 这里只是想告诉你引用和指针十分相似,但是,引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

1.3 引用作函数参数

        关于值传递、地址传递和引用传递,我们用交换函数来举例子

1.值传递

void swap_zhi(int a, int b)
{
	int t = a;
	a = b;
	b = t;
}

2.地址传递

void swap_dizhi(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

3.引用传递

void swap_yinyong(int &aa, int &bb)
{
	int t = aa;
	aa = bb;
	bb = t;
}

现在我们用一串代码来将他们作比较

void swap_zhi(int a, int b)
{
	int t = a;
	a = b;
	b = t;
	cout << "值传递函数内部传递" << endl;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
}

void swap_dizhi(int *a, int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
	cout << "地址传递函数内部传递" << endl;
	cout << "a=" << *a << endl;
	cout << "b=" << *b << endl;
}

void swap_yinyong(int &aa, int &bb)
{
	int t = aa;
	aa = bb;
	bb = t;
	cout << "引用传递函数内部传递" << endl;
	cout << "a=" << aa << endl;
	cout << "b=" << bb << endl;
}
int main()
{

	int a = 10;
	int b = 100;
	swap_zhi(a, b);
	cout << "调用值传递函数结果" << endl;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;

	swap_dizhi(&a, &b);
	cout << "调用地址传递函数结果" << endl;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;

	a = 10;//地址传递修改成了100 10,我们再把他改回来,便于观察
	b = 100;

	swap_yinyong(a, b);
	cout << "调用引用传递函数结果" << endl;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
}

 

从上面的对比我们可以看出,值传递无法改变变量的值,只能能在函数内修改变量,而地址传递和引用传递可以修改变量的值 

专业说法就是,值传递,形参不会修饰实参,而地址传递和引用传递可以。

1.4 引用作函数返回值

1.不能返回局部变量的引用

int& test()
{
	int a = 10;//局部变量存放在四区的栈区,用完就释放
	return a;
}

int main()
{
	int& ref = test();
	cout << "ref=" << ref << endl;
	cout << "ref=" << ref << endl;

	getchar();
	return 0;
}

 这里又有同学有疑问了,为什么第一次是对的,栈区不是用完释放吗,其实是因为编译器做了保留,但其实这一块的内容我们已经没有权利去操作他了,所以第二次是错的。

举个例子就很好理解了,因为某些原因,高数课宾宾和卷天没坐在一起,高数课结束了,卷天想找到宾宾,于是大喊“卷宾”,但是卷天怎么喊都找不到宾宾,因为宾宾下课后回宿舍学3D建模去了,高数课就是一个函数,而宾宾是函数的内部变量,函数结束就是高数课下课了,宾宾回宿舍就是局部变量被回收了。

如果我们执意想要返回引用的局部变量怎么办?

方法是将其变成静态变量。

int& test()
{
	static int a = 10;//静态变量放在全局区,全局区上的数据程序结束后系统释放
	return a;
}

int main()
{
	int& ref = test();
	cout << "ref=" << ref << endl;
	cout << "ref=" << ref << endl;

	getchar();
	return 0;
}

 

 也就是说卷天执意要找到宾宾,那就让宾宾下课后等他就行了。

但这样不推荐,看下面就明白了。

2.函数的调用可以作为左值

int& test()
{
	static int a = 10;
	return a;
}

int main()
{
	int& ref = test();
	cout << "ref=" << ref << endl;
	cout << "ref=" << ref << endl;
	test() = 1000;
	cout << "ref=" << ref << endl;
	cout << "ref=" << ref << endl;

	getchar();
	return 0;
}

 妙不妙?

真是 妙蛙种子吃着妙脆角进了米奇妙妙屋 妙到家了!

test调用完之后返回的是a的引用,再对test进行操作其实就是对a的操作,而ref又是test的外号。

赋值操作后,再用别名来访问这块内存,其实这块内存已经被修饰掉了。

别忘了,引用其实就是起外号。

二、引用的本质

本质:引用的本质在c++内部实现是一个指针常量

void test(int& ref)
{
	ref = 100;//ref是引用,转换为*ref = 100
}int main()
{
	int a = 10;

	//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可以更改
	int& ref = a;
	ref = 20;//内部发现ref是引用,自动帮我们转换为:*ref = 20;

	cout << "a=" << a << endl;
	cout << "ref=" << ref << endl;

	test(a);


	getchar();
	return 0;
}

三、引用的使用场景

3.1 指针的引用

3.2 常量的引用

能力有限,以后再写  

 本文参考b站视频黑马程序员,有兴趣可以去b站自行搜索,第一次写博客,组长的任务罢了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/347106.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号