C++ 引用
在C++ 中,我们可以使用变量(variable)来存储数据,变量有两个重要的属性:类型(type)和值(value)。类型决定了变量可以存储什么样的数据,以及可以进行什么样的操作,例如int
类型的变量可以存储整数,可以进行加减乘除等算术运算。值决定了变量存储的具体的数据,例如int a = 10;
就是定义了一个int
类型的变量a
,并赋值为10
。
除了类型和值之外,变量还有另一个重要的属性:地址(address)。地址是变量在内存中的位置,可以用一个十六进制的数来表示,例如0x7fffbf4c
。我们可以使用取地址运算符(&)来获取变量的地址,例如&a
就是获取变量a
的地址。地址是变量的唯一标识,不同的变量有不同的地址,同一个变量在不同的时间也可能有不同的地址,因为变量可能被分配到不同的内存空间。
有了地址,我们就可以使用指针(pointer)来操作变量。指针是一种特殊的变量,它的类型是指针类型(pointer type),它的值是地址值(address value),它的作用是指向(point to)另一个变量。我们可以使用指针运算符(*)来获取指针指向的变量的值,例如*p
就是获取指针p
指向的变量的值。指针的优点是可以间接地访问和修改变量的值,而不需要知道变量的名字,这样可以提高代码的灵活性和效率。指针的缺点是容易出错,因为指针可能指向一个不存在或者无效的地址,导致程序崩溃或者数据损坏。
为了解决指针的缺点,C++ 引入了一种新的概念:引用(reference)。引用是一种特殊的变量,它的类型是引用类型(reference type),它的值是别名(alias),它的作用是引用(refer to)另一个变量。引用的本质是一个常量指针,它在定义时必须初始化为一个已存在的变量的地址,然后就可以使用引用的名字来访问和修改被引用的变量的值,而不需要使用指针运算符。引用的优点是可以直接地访问和修改变量的值,而不需要知道变量的地址,这样可以提高代码的可读性和安全性。引用的缺点是不能改变引用的目标,一旦引用被初始化为一个变量,就不能再引用另一个变量。
引用的定义和使用
引用的定义和使用有以下的规则和注意事项:
- 引用的定义格式为:
Type & name = var;
,其中Type
是被引用的变量的类型,name
是引用的名字,var
是被引用的变量的名字。例如,int &a = b;
就是定义了一个int
类型的引用a
,并初始化为变量b
。 - 引用的定义时必须进行初始化,不能定义一个空引用,也不能定义一个指向无效地址的引用。例如,
int &a;
或者int &a = 10;
都是错误的,因为没有指定引用的目标。 - 引用的初始化后不能改变引用的目标,即不能让引用指向另一个变量。例如,
int &a = b; a = c;
并不是让引用a
指向变量c
,而是让变量b
的值变成和变量c
一样。 - 引用的类型必须和被引用的变量的类型一致,或者可以进行隐式类型转换。例如,
int &a = b;
中,a
和b
的类型都必须是int
,或者b
的类型可以隐式转换为int
,例如char
、short
等。 - 引用的名字可以和被引用的变量的名字相同,但是不建议这样做,因为会造成混淆。例如,
int a = 10; int &a = a;
是合法的,但是不推荐。
下面是一个引用的定义和使用的例子:
#include <iostream>
using namespace std;
int main() {
// 定义一个普通的变量
int a = 10;
// 定义一个引用,初始化为变量a
int &b = a;
// 输出变量a和引用b的值和地址
cout << "a = " << a << ", &a = " << &a << endl;
cout << "b = " << b << ", &b = " << &b << endl;
// 修改引用b的值,相当于修改变量a的值
b = 20;
// 输出变量a和引用b的值和地址
cout << "a = " << a << ", &a = " << &a << endl;
cout << "b = " << b << ", &b = " << &b << endl;
return 0;
}
输出结果为:
a = 10, &a = 0x7ffeeb9f8a64
b = 10, &b = 0x7ffeeb9f8a64
a = 20, &a = 0x7ffeeb9f8a64
b = 20, &b = 0x7ffeeb9f8a64
从输出结果可以看出,变量a
和引用b
的值和地址都是相同的,说明引用b
就是变量a
的别名,通过引用b
可以直接访问和修改变量a
的值。
引用作为函数参数
引用的一个重要的用途是作为函数的参数,这样可以实现以下的目的:
- 减少函数调用的开销,避免复制大量的数据,提高程序的效率。
- 实现函数的多个返回值,通过引用参数可以修改实参的值,从而返回更多的信息。
- 实现函数的重载,通过不同类型的引用参数可以区分不同的函数,从而实现多态。
引用作为函数参数有以下的规则和注意事项:
- 引用参数的定义格式为:
Type & name
,其中Type
?是被引用的变量的类型,name
?是引用的名字。例如,void swap(int &a, int &b)
?就是定义了一个交换两个整数的函数,它的参数是两个整数的引用。 - 引用参数的调用格式为:
var
,其中var
?是被引用的变量的名字。例如,swap(x, y)
?就是调用交换两个整数的函数,它的实参是两个整数的变量x
?和y
。 - 引用参数的作用是将实参的地址传递给形参,从而使形参和实参指向同一个变量,通过形参可以直接访问和修改实参的值,而不需要返回值。例如,
swap(x, y)
?就是将变量x
?和y
?的地址传递给引用a
?和b
,从而使a
?和x
,b
?和y
?指向同一个变量,通过a
?和b
?可以直接交换x
?和y
?的值,而不需要返回值。 - 引用参数的优点是可以减少函数调用的开销,避免复制大量的数据,提高程序的效率。例如,如果我们要交换两个数组的值,如果使用普通的参数,就需要复制两个数组的所有元素,这样会占用大量的内存和时间,如果使用引用参数,就只需要传递两个数组的地址,这样会节省大量的内存和时间。
- 引用参数的优点是可以实现函数的多个返回值,通过引用参数可以修改实参的值,从而返回更多的信息。例如,如果我们要计算两个整数的最大公约数和最小公倍数,如果使用普通的参数,就只能返回一个值,如果使用引用参数,就可以返回两个值,一个是最大公约数,一个是最小公倍数。
- 引用参数的优点是可以实现函数的重载,通过不同类型的引用参数可以区分不同的函数,从而实现多态。例如,如果我们要定义一个打印函数,可以根据不同类型的引用参数来重载打印函数,从而实现对不同类型的数据的打印。
下面是一个引用作为函数参数的例子:
#include <iostream>
using namespace std;
// 定义一个交换两个整数的函数,参数是两个整数的引用
void swap(int &a, int &b) {
// 定义一个临时变量,用于存储一个整数的值
int temp = a;
// 将第二个整数的值赋给第一个整数
a = b;
// 将临时变量的值赋给第二个整数
b = temp;
}
// 定义一个计算两个整数的最大公约数和最小公倍数的函数,参数是两个整数的值和两个整数的引用
void gcd_lcm(int a, int b, int &gcd, int &lcm) {
// 定义一个临时变量,用于存储两个整数的乘积
int product = a * b;
// 使用辗转相除法求最大公约数
while (b != 0) {
int r = a % b;
a = b;
b = r;
}
// 将最大公约数赋给引用参数
gcd = a;
// 使用公式求最小公倍数
lcm = product / gcd;
}
// 定义一个打印整数的函数,参数是一个整数的引用
void print(int &a) {
// 输出整数的值
cout << "The integer is: " << a << endl;
}
// 定义一个打印字符串的函数,参数是一个字符串的引用
void print(string &s) {
// 输出字符串的内容
cout << "The string is: " << s << endl;
}
// 主函数,用于测试
int main() {
// 定义两个整数变量
int x = 10;
int y = 20;
// 调用交换函数,实现两个整数的交换
swap(x, y);
// 输出交换后的结果
cout << "x = " << x << ", y = " << y << endl; // 输出结果为:x = 20, y = 10
// 定义两个整数变量
int a = 12;
int b = 18;
// 定义两个整数变量,用于存储最大公约数和最小公倍数
int gcd, lcm;
// 调用计算函数,实现两个整数的最大公约数和最小公倍数的计算
gcd_lcm(a, b, gcd, lcm);
// 输出计算后的结果
cout << "The gcd of " << a << " and " << b << " is: " << gcd << endl; // 输出结果为:The gcd of 12 and 18 is: 6
cout << "The lcm of " << a << " and " << b << " is: " << lcm << endl; // 输出结果为:The lcm of 12 and 18 is: 36
// 定义一个整数变量
int c = 100;
// 调用打印函数,实现整数的打印
print(c); // 输出结果为:The integer is: 100
// 定义一个字符串变量
string s = "Hello";
// 调用打印函数,实现字符串的打印
print(s); // 输出结果为:The string is: Hello
return 0;
}
从上面的代码可以看出,引用作为函数参数可以实现以下的目的:
- 减少函数调用的开销,避免复制大量的数据,提高程序的效率。例如,
swap(x, y)
?就是通过引用参数来交换两个整数的值,而不需要复制两个整数的值。 - 实现函数的多个返回值,通过引用参数可以修改实参的值,从而返回更多的信息。例如,
gcd_lcm(a, b, gcd, lcm)
?就是通过引用参数来返回两个整数的最大公约数和最小公倍数,而不需要返回一个值。 - 实现函数的重载,通过不同类型的引用参数可以区分不同的函数,从而实现多态。例如,
print(c)
?和print(s)
?就是根据不同类型的引用参数来调用不同的打印函数,从而实现对不同类型的数据的打印。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!