35.引用-引用和函数
35.1 知识点
使用引用传递函数参数
左值引用参数函数
此函数接收左值引用作为参数,允许在函数内部修改原始对象。避免了参数传递时的拷贝操作,提高性能,同时函数内的操作直接影响传入的对象。
遵守引用使用的一般规则:
- 引用变量的类型必须和引用的内容类型一致。
- 引用绑定的对象不能更改(指引用的绑定关系,而不是引用所指向对象的值)。
- 引用不会占用新的内存空间,它只是原变量的另一种名称。
- 传递引用时,对象的生命周期取决于外部,不会因函数调用结束而释放。
void changeValue(int& value)
{
// 修改引用所指向的对象的值
value = 10;
}
// 调用左值引用参数函数,传入的实参在函数里修改了值,外面的实参也会相应改变
int a = 99;
changeValue(a);
cout << "修改后 a 的值: " << a << endl; // 10
右值引用参数函数
右值引用主要用于优化性能,特别是对于临时对象或大对象,避免不必要的拷贝。可以直接操作传入的右值,提升程序效率。虽然目前可能难以完全理解其优势,但在更复杂的场景中会更明显。
void changeValue(int&& value)
{
// 输出右值的值
cout << "传入的右值: " << value << endl;
}
// 对于右值引用参数,可以利用它避免不必要的临时对象创建,从而优化性能和节约内存
// 直接将右值作为参数传入函数
changeValue(10); // 10
常量引用参数
常量引用参数函数接收常量引用作为参数,保证函数内不会修改引用所指向的对象。适用于只读操作,避免拷贝开销,特别是对于大型对象或不可修改的对象。通常在左值引用参数上使用 const
,而右值引用加 const
的意义不大。
void getValue(const int& value)
{
// 尝试修改常量引用会导致编译错误
// value = 10;
// 输出常量引用的值
cout << "常量引用的值: " << value << endl;
}
// 使用常量引用参数的函数调用,适用于只读操作,避免不必要的拷贝
getValue(666); // 666
函数返回引用
函数返回引用时需要注意:不能返回局部变量的引用,因为局部变量在函数结束时会被销毁,返回其引用会导致未定义行为。此函数返回传入参数的引用,使用时需注意引用的生命周期。
int& getRef(int& d)
{
// 错误示例,以下代码会导致未定义行为,因为 b 是局部变量,函数结束后被销毁
// int b = 10;
// return b;
// 正确示例,返回传入参数的引用
return d;
}
int c = 99;
int& d = getRef(c);
// 修改 d 的值,由于 d 是 c 的引用,c 的值也会相应改变
d = 888;
cout << "修改后 c 的值: " << c << endl; // 888
35.2 知识点代码
Lesson35_引用_引用和函数.cpp
#include <iostream>
using namespace std;
// 函数声明
void changeValue(int& value);
void changeValue(int&& value);
void getValue(const int& value);
int& getRef(int& d);
int main()
{
std::cout << "引用和函数\n";
#pragma region 知识点一 使用引用传递函数参数
// 调用左值引用参数函数,传入的实参在函数里修改了值,外面的实参也会相应改变
int a = 99;
changeValue(a);
cout << "修改后 a 的值: " << a << endl;//10
// 对于右值引用参数,可以利用它避免不必要的临时对象创建,从而优化性能和节约内存
// 直接将右值作为参数传入函数
changeValue(10);//10
#pragma endregion
#pragma region 知识点二 常量引用参数
// 使用常量引用参数的函数调用,适用于只读操作,避免不必要的拷贝
getValue(666);//666
#pragma endregion
#pragma region 知识点三 函数返回引用
int c = 99;
int& d = getRef(c);
// 修改 d 的值,由于 d 是 c 的引用,c 的值也会相应改变
d = 888;
cout << "修改后 c 的值: " << c << endl;//888
#pragma endregion
}
#pragma region 知识点一 使用引用传递函数参数
// 左值引用参数函数
// 此函数接收左值引用作为参数,允许在函数内部修改原始对象
// 避免了参数传递时的拷贝操作,提高性能,同时函数内的操作直接影响传入的对象
// 遵守引用使用的一般规则:
// 1. 引用变量的类型必须和引用的内容类型一致
// 2. 引用绑定的对象不能更改(指引用的绑定关系,而不是引用所指向对象的值)
// 3. 引用不会占用新的内存空间,它只是原变量的另一种名称
// 4. 传递引用时,对象的生命周期取决于外部,不会因函数调用结束而释放
void changeValue(int& value)
{
// 修改引用所指向的对象的值
value = 10;
}
// 右值引用参数函数
// 主要用于优化性能,特别是对于临时对象或大对象,避免不必要的拷贝
// 可以直接操作传入的右值,提升程序效率
// 目前可能难以完全理解其优势,后续在更复杂的场景中会更明显
void changeValue(int&& value)
{
// 输出右值的值
cout << "传入的右值: " << value << endl;
}
#pragma endregion
#pragma region 知识点二 常量引用参数
// 常量引用参数函数
// 接收常量引用作为参数,保证函数内不会修改引用所指向的对象
// 适用于只读操作,避免拷贝开销,特别是对于大型对象或不可修改的对象
// 通常在左值引用参数上使用 const,右值引用加 const 意义不大
void getValue(const int& value)
{
// 尝试修改常量引用会导致编译错误
// value = 10;
// 输出常量引用的值
cout << "常量引用的值: " << value << endl;
}
#pragma endregion
#pragma region 知识点三 函数返回引用
// 函数返回引用
// 注意:不能返回局部变量的引用,因为局部变量在函数结束时会被销毁,返回其引用会导致未定义行为
// 此函数返回传入参数的引用,使用时需注意引用的生命周期
int& getRef(int& d)
{
// 错误示例,以下代码会导致未定义行为,因为 b 是局部变量,函数结束后被销毁
// int b = 10;
// return b;
// 正确示例,返回传入参数的引用
return d;
}
#pragma endregion
35.3 练习题
请为一维数组、二维数组、指针声明一个引用别名
// 一维数组
int arr[5] = { 1, 2, 3, 4, 5 };
// 二维数组
int arr2D[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
// 普通 int 指针
int x = 10;
int* ptr = &x;
// 普通的和单个变量绑定引用 用于在语法上和下面其他引用对比
int& refX = x;
// 为一维数组声明引用别名
int(&arr1)[5] = arr; // arr1一个别名了
typedef int(&arrRef)[5];
arrRef ref_arr = arr; // ref_arr是一个别名了
// 为二维数组声明引用别名
int(&arr2D1)[3][4] = arr2D; // arr2D1一个别名了
typedef int(&arr2DRef)[3][4];
arr2DRef ref_arr2D = arr2D; // ref_arr2D是一个别名了
// 为普通 int 指针声明引用别名
int*& ptrRef = ptr;
// 输出元素验证
cout << "一维数组引用元素: " << arr1[1] << endl; // 2
cout << "一维数组引用元素: " << ref_arr[2] << endl; // 3
cout << "二维数组引用元素: " << arr2D1[0][0] << endl; // 1
cout << "二维数组引用元素: " << ref_arr2D[1][1] << endl; // 6
cout << "指针引用元素: " << *ptrRef << endl; // 10
编写一个函数,接收一个 int 类型的左值引用作为参数,将其值加1。调用该函数后,验证原变量的值是否被修改
void addRef(int& value)
{
value += 1;
}
int bb = 22;
addRef(bb);
cout << bb << endl; // 23
编写一个函数,返回一个数组中某个元素的左值引用,并通过该引用修改数组中元素的值
int& changeArrayValue(int array[], int index)
{
return array[index];
}
int array[] = { 1, 2, 3, 4, 5 };
// int& value = changeArrayValue(array, 2);
// value = 99;
changeArrayValue(array, 2) = 99;
for (int i = 0; i < 5; i++)
{
cout << array[i] << endl;
}
// 1 2 99 4 5
编写一个函数,使用 const 左值引用接收参数并打印参数值,确保函数能接受左值和右值
// 对于常量左值引用参数来说,不仅可以传入左值,也可以传入右值
void test(const int& value)
{
cout << value << endl;
}
// 对于常量左值引用参数来说,不仅可以传入左值,也可以传入右值
int cc = 666;
test(cc); // 666
test(999); // 999
35.4 练习题代码
Lesson35_练习题.cpp
#include <iostream>
using namespace std;
void addRef(int& value);
int& changeArrayValue(int array[], int index);
void test(const int& value);
int main()
{
std::cout << "引用和函数练习题\n";
#pragma region 练习题一
// 一维数组
int arr[5] = { 1, 2, 3, 4, 5 };
// 二维数组
int arr2D[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
// 普通 int 指针
int x = 10;
int* ptr = &x;
//普通的和单个变量绑定引用 用于在语法上和下面其他引用对比
int& refX = x;
// 为一维数组声明引用别名
int(&arr1)[5] = arr;//arr1一个别名了
typedef int(&arrRef)[5];
arrRef ref_arr = arr;//ref_arr是一个别名了
// 为二维数组声明引用别名
int(&arr2D1)[3][4] = arr2D;//arr2D1一个别名了
typedef int(&arr2DRef)[3][4];
arr2DRef ref_arr2D = arr2D;//ref_arr2D是一个别名了
// 为普通 int 指针声明引用别名
int*& ptrRef = ptr;
// 输出元素验证
cout << "一维数组引用元素: " << arr1[1] << endl;//2
cout << "一维数组引用元素: " << ref_arr[2] << endl;//3
cout << "二维数组引用元素: " << arr2D1[0][0] << endl;//1
cout << "二维数组引用元素: " << ref_arr2D[1][1] << endl;//6
cout << "指针引用元素: " << *ptrRef << endl;//10
#pragma endregion
#pragma region 练习题二
int bb = 22;
addRef(bb);
cout << bb << endl;//23
#pragma endregion
cout << "******************" << endl;
#pragma region 练习题三
int array[] = { 1,2,3,4,5 };
/*int& value = changeArrayValue(array, 2);
value = 99;*/
changeArrayValue(array, 2) = 99;
for (int i = 0; i < 5; i++)
{
cout << array[i] << endl;
}
// 1 2 99 4 5
#pragma endregion
cout << "******************" << endl;
#pragma region 练习题四
//对于 常量左值引用参数来说 不仅可以传入左值 也可以传入右值
int cc = 666;
test(cc);//666
test(999);//999
#pragma endregion
}
#pragma region 练习题一
//请为一维数组、二维数组、指针
//声明一个引用别名
#pragma endregion
#pragma region 练习题二
//编写一个函数,接收一个 int 类型的左值引用作为参数,将其值加1
//调用该函数后,验证原变量的值是否被修改
void addRef(int& value)
{
value += 1;
}
#pragma endregion
#pragma region 练习题三
//编写一个函数,返回一个数组中某个元素的左值引用,
//并通过该引用修改数组中元素的值
int& changeArrayValue(int array[], int index)
{
return array[index];
}
#pragma endregion
#pragma region 练习题四
//编写一个函数,使用 const 左值引用接收参数并打印参数值,确保函数能接受左值和右值
//对于 常量左值引用参数来说 不仅可以传入左值 也可以传入右值
void test(const int& value)
{
cout << value << endl;
}
#pragma endregion
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com