引用
引用:**给变量起一个别名**
语法:数据类型 &别名=原名;
- 引用一定要初始化
int &c;//错误,要让b初始化引用指向a - 引用初始化后,不能更改
int &c=a;
int &c=b;//错误,不能更改引用的指向 - 不要返回局部变量的引用,值会改变
- 函数的返回值为引用的时候,函数调用可以作为左值(等式左边)
- 引用本质:指针常量;指向不可以修改,指向的值可以修改
int &ref = a;//自动转换 int* const ref = & a;//指针常量
ref = 20;//内部发现ref是引用,自动转化为*ref = 20; - 常量引用 const int& ref =10;
C++推荐使用引用,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了
#include <iostream>
#include <string>
using namespace std;
//创建引用
int g_a = 10;
int g_b = 10;
int& c = g_a;
//int& c = g_b;///错误,不能更改引用的指向
void swap(int &a, int &b) {//引用传递,形参会修饰实参
int temp = b;
b = a;
a = temp;
}
int& test01() {//不要返回局部变量的引用
int l_a = 10;
return l_a;
}
int& test02() {//不要返回局部变量的引用
static int static_b = 10;
return static_b;
}
void showValue(const int& ref) {//使用常量引用,让变量只能被访问,不能修改
//ref += 10;//只能被访问,不能修改
cout << "打印g_a="<< ref << endl;
}
void main() {
cout << "原始a,b的值" << endl;
cout << "g_a=" << g_a << endl;
cout << "g_b=" << g_b << endl;
c = 20;
cout << endl << "修改引用c后(c引用a),g_a,g_b的值" << endl;
cout << "g_a=" << g_a << endl;
cout << "g_b=" << g_b << endl;
swap(g_a, g_b);//引用传递,形参会修饰实参
cout << endl << "引用传递后(swap(int &a, int &b)),g_a,g_b的值" << endl;
cout << "g_a=" << g_a << endl;
cout << "g_b=" << g_b << endl;
cout << endl << "不要返回局部变量的引用,值会改变,因为数据存放在栈区" << endl;
int &return_l_a = test01();
cout << "l_a=" << return_l_a << endl;
cout << "l_a=" << return_l_a << endl;
cout << "l_a=" << return_l_a << endl;
int& return_l_b = test02();
cout << endl << "全局变量的引用,值会不会变,因为数据存放在全局区" << endl;
cout << "static_b=" << return_l_b << endl;
cout << "static_b=" << return_l_b << endl;
cout << "static_b=" << return_l_b << endl;
test02() = 123;//函数的返回值为引用的时候,函数调用可以作为左值(等式左边),修改static_b=1123;
cout << endl << "函数调用作为左值(等式左边),修改static_b" << endl;
cout << "static_b=" << return_l_b << endl;
//int& ref = 10; 引用本身需要一个合法的内存空间,因此这行错误
//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;
const int& ref = 10;
//ref = 100; //加入const后不可以修改变量
cout << endl << "常量引用ref="<< ref << endl;
showValue(g_a);
}
常量指针、指针常量
- 语法:
常量指针:const int* p = &a;
指针常量:int* const p = &a;
常量指针常量:const int* const p = &a;
总结:
常量指针:本质指针,指向的对象是常量,不能通过指针来修改指向对象,但是其本身是一个变量,因此可以被重新赋值
指针常量:本质常量,常量的值是一个指针,指向不能变,指向的内容可变
常量指针常量:常量指针+指针常量
#include<iostream>
using namespace std;
void main() {
int a = 100;
int b = 200;
const int* p1 = &a;
int* const p2 = &a;
const int* const p3 = &a;
//1.常量指针
//*p = 200;//错误,不能通过指针来修改指向对象
p1 = &b;//但是其本身是一个变量,因此可以被重新赋值
cout << *p1 << endl;
//2.指针常量
//p2 = &b; //错误,指向不能变,指向的内容可变
*p2 = 150;
cout << *p2 << endl;
cout << a << endl;
//3.常量指针常量:常量指针 + 指针常量
//*p3 = 200;//错误,指向的内容不能变
//p3 = &b;//错误,指向不能变
}
指针函数、函数指针
- 指针函数:返回值为指针的函数
- 函数指针:指向函数的指针
总结:
函数名本身就是一个地址,就是一个函数指针
函数指针可以作为参数进行传递
#include<iostream>
using namespace std;
int* ptr_a(int& val) {//返回指针,指针函数
val = val + 1;
return &val;
}
int& ptr_b(int& val) {//返回引用,指针函数
val = val + 1;
return val;
}
int ptr_c(int& val) {//普通函数
val = val + 1;
return val;
}
void test_() {
int value = 1;
//返回指针,指针函数
int* p1 = ptr_a(value);
cout << "value:" << value << "\t\t*p1:" << *p1 << endl;
//返回引用,指针函数
int& p2 = ptr_b(value);
p2++;
cout << "value:" << value << "\t\tp2:" << p2 << endl;
//普通函数,来定义成函数指针
// 直接定义
int (*func_ptr)(int&);//定义一个指针,指向函数(返回值为int,参数为int&)
func_ptr = ptr_c;//赋值
func_ptr(value);
cout << "value:" << value << endl;
//typedef
typedef int(*func_ptr2)(int&);//用typedef给函数指针(返回值为int,参数为int&)别名func_ptr2
func_ptr2 ptr1 = ptr_c;//定义一个函数指针,并赋值
ptr1(value);//利用函数指针调用函数
cout << "value:" << value << endl;
//using,推荐使用
using func_ptr3 = int(*)(int&);//用using给函数指针(返回值为int,参数为int&)别名func_ptr3
func_ptr3 ptr2 = ptr_c;//定义一个函数指针,并赋值
ptr2(value);//利用函数指针调用函数
cout << "value:" << value << endl;
}
void main() {
test();
}
函数高级
- 函数默认参数 返回值类型 函数名(参数= 默认值){}
//1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
//2. 如果函数声明有默认值,函数实现的时候就不能有默认参数(函数声明和实现只能有一个有默认参数)
int func(int a=10; int b=10);//函数声明
int func(int a=10; int b=10){return a+b;}//函数实现
//上述例子错误,函数声明和实现只能有一个有默认参数
int func(int a; int b);//函数声明
int func(int a=10; int b=10){return a+b;}//函数实现
//3. 有传入的参数就用传入的参数,没有就要用默认值 - 函数占位参数 返回值类型 函数名 (数据类型){} void func(int a, int) {}
//1. C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置
//2. 函数占位参数 ,占位参数也可以有默认参数 void func(int a, int = 10) {}
//3. 在现阶段函数的占位参数存在意义不大,但是后面的课程中会用到该技术 - 函数重载 函数名可以相同,提高复用性
//1. 满足条件:同一个作用域下;函数名称相同;函数参数类型不同或者个数不同或者顺序不同;
//2. 函数返回值不可以作为函数重载条件
//3. 注意: * 引用作为重载条件 函数重载碰到函数默认参数
#include <iostream>
#include <string>
using namespace std;
//函数默认参数
int sum_3(int a, int b = 10, int c = 10) {//求三数之和
return a + b + c;
}
//函数占位参数
void placeholder(int a, int) {
cout << "This is placeholder func." << endl;
}
//引用作为重载条件
void ref_overloading(int& a)
{
cout << "ref_overloading (int &a) 调用 " << endl;
}
void ref_overloading(const int& a)
{
cout << "ref_overloading (const int &a) 调用 " << endl;
}
//默认参数碰到函数重载
void def_overloading(int a,int b = 10) {
cout << "def_overloading (int a; int b = 10) 调用 " << endl;
}
void def_overloading(int a) {
cout << "def_overloading (int a) 调用 " << endl;
}
void main() {
//调用有默认参数的函数时,默认的参数位置可以传值也可不传
cout << "默认参数" << endl;
cout << "sum_3 = " << sum_3(20, 20) << endl;
cout << "sum_3 = " << sum_3(100) << endl;
//调用有占位参数(非默认)的函数时,占位参数必须填补,占位参数为默认参数时可填补可不填补
cout << endl << "占位参数" << endl;
placeholder(10, 10); //占位参数必须填补
//引用作为重载条件,根据传入的类型调用,指针常量(调用无const),常量指针常量(调用const)
int a = 10;
const int b = 10;
cout << endl << "引用作为重载条件" << endl;
ref_overloading(a); //a为变量,调用无const
ref_overloading(b); //b为常量,调用const
ref_overloading(10);//int &a = 10 不合法,const int &a = 10 合法;所以调用有const
//默认参数碰到函数重载
cout << endl << "默认参数碰到函数重载" << endl;
//def_overloading(10);//报错,不知道调用哪个
def_overloading(10, 10);
}
本文详细介绍了C++中的引用概念,包括引用的初始化、不可变性和作为函数参数的使用。同时,探讨了指针的不同形式,如常量指针、指针常量和常量指针常量。此外,还讨论了指针函数和函数指针的用法,以及函数的默认参数、占位参数和重载。最后,展示了如何在实际代码中应用这些概念。
1104

被折叠的 条评论
为什么被折叠?



