C++引用
引用是什么?
引用是变量的别名
基本数据类型引用
int a = 3;
int &b = a; //引用必须初始化
结构体类型的引用
//定义一个结构体
typedef struct
{
int x;
int y;
}Coor;
#include <iostream>
using namespaces std;
int main()
{
Coor c1;
Coor &c = c1; //结构体类型引用
c.x = 10;
c.y = 20;
cout << c1.x << c1.y;
return 0;
}
指针类型的引用
格式:
类型 *&指针引用名 = 指针;
#include <iostream>
using namespaces std;
int main()
{
int a = 10;
int *p = &a;
int *&q = p; //指针类型的引用
*q = 20;
cout << a << endl;
return 0;
}
引用作函数参数
//实现一个交换值的函数
//没有引用时单纯用指针传参数
void fun(int *a, int *b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}
int x = 10, y = 20;
fun(&x, &y);
//引用作函数参数
void fun(int &a, int &b) //引用作为参数,起了别名a, b
{
int c = 0;
c = a;
a = b;
b = c;
}
int x = 10, y = 20;
fun(x, y); // 相当于给x取别名a,给y取别名b
C++ 语言引用代码演示
#include <iostream>
#include <stdlib.h>
using namespaces std;
typedef struct
{
int x;
int y;
}Coord;
void fun(int &a, int &b);
int main()
{
//基本数据类型的引用
int a = 10;
# int &b = NULL; //如果这样写会报错,只有别名无法成立,引用不能单独存在,引用必须初始化
int &b = a;
b = 20;
cout << a << endl; // 输出20
a = 30;
cout << b << endl; // 输出30
// 结构体类型的引用
Coord c;
Coord &c1 = c;
c1.x = 10;
c1.y = 20;
cout << c.x << ", " << c.y << endl;
// 指针类型的引用
int a = 3;
int *p = a;
int *&q = p;
*q = 5; //通过*q访问a
cout << a << endl;
// 引用作函数的参数
int x = 10;
int y = 20;
cout << x << ", " << y << endl;
fun(x, y);
cout << x << "," << y << endl;
system("pause");
return 0;
}
void fun(int &a, int &b)
{
int c = 0;
c = a;
a = b;
b = c;
}
C++ 语言 const 关键字
控制变化的 const
const 与基本数据类型
int x = 3;
变量名 | 存储地址 | 存储内容 |
---|---|---|
x | &x | 3 (变量) |
const int x = 3; //常量
变量名 | 存储地址 | 存储内容 |
---|---|---|
x | &x | 3 (常量) |
const 与指针类型
1. const int*p = NULL;
2. int const *p = NULL;
// 1和2代码完全等价
//但是 int * const p = NULL; 表示其他含义
// const 可以一处加, 也可以两处加const
3. const int * const p = NULL;
4. int const * const p = NULL;
// 3和4代码完全等价
下面来看一个例子
int x = 3; const int *p = &x;
//p = &y; 正确 //*P = 4; 错误
变量名 | 存储地址 | 存储内容 |
---|---|---|
x | &x | 3 |
p | &p | &x |
另一个例子
int x = 3; int *const p = &x; //p=&y; 将会是错误的
变量名 | 存储地址 | 存储内容 |
---|---|---|
x | &x | 3 |
p | &p | &x (常量) |
再一个例子
const int x = 3; const int *const p = &x;
// p = &y; *p = 4; 都是错误的
// const int *const p = &x; 两个const, 则不能够通过p修改常量的值
const 与引用
int x = 3; const int &y = x;
// x = 10; 正确 // y = 20; 错误
// y 作为 x 的别名,在前面加了个const , 则不允许通过y修改x的值, 但可以通过变量名x本身修改
const 使用错误示例
1. const int x = 3; x = 5;
2. int x = 3; const int y = x; y = 5;
3. int x = 3; const int *y = &x; *y = 5;
错误题目
判断: int const a = 3; int *p = &a;
这是错的
原因:
变量的权限比常量const的权限要高,而计算机允许权限高的变量赋值给权限低的常量
const 的小总结
(1)常量的地址不能赋值给指针
(2)const 放在int 前或者放在int 后都是等价的,但是放在 * 号前和 * 号后是不同的,要加以区分。
(3)指针指向const修饰的变量时 , 应该是const int const *p = &a ; (被引用者的权限应该大于或等于引用者)
(4)常引用作为函数的参数,void fun(const int &a,const int &b);
C++ 函数新特性
函数参数默认值
void fun(int i, int j=5, int k=10)
// 参数j和k有了默认值
但是,下面的写法是错误的
void fun(int i, int j=5, int k) //这是错误的
有默认参数值的参数必须在参数表的最右端
函数在声明时可以写参数默认值,但是在定义时不要写默认值
使用示例
#include <iostream>
void fun(int i, int j=5, int k=10)
int main()
{
fun(20); //相当于fun(20, 5, 10);
fun(20, 30); //相当于fun(20, 30, 10);
fun(20, 30, 40); //相当于fun(20, 30, 40);
}
void fun(int i, int j, int k)
{
cout << i << j << k <<endl;
}
无实参则用默认值,否则实参覆盖默认值
函数重载
什么是函数重载?
在相同作用域内, 用同一函数名定义的多个函数, 参数个数和参数类型不同
代码示例
int getMax(int x, int y, int z)
{
//to do
}
double getMax(double x, double y)
{
//to do
}
思考:编译器如何识别重载的函数?
第一个函数相当于getMax_int_int_int
第二个函数相当于getMax_double_double
内联函数
内联函数与普通函数的区别:
代码示例
内联函数关键字:inline
inline int max(int a, int b, int c)
int main()
{
int i = 10, j = 20, k = 30, m;
m = max(i, j ,k);
cout << "max=" << m << endl;
return 0;
}
讲上面的代码展开之后, 就可以得到:
int main()
{
int i = 10, j = 20, k = 30, m;
int a, b, c;
a = i; b = j; c = k;
if(b > a) a = b;
if(c > a) a = c;
m = a;
cout << "max=" << m << endl;
return 0;
}
思考:为什么不所有函数都使用内联方式呢?
- 内联编译时建议性的,由编译器决定。
- 逻辑简单而且调用频繁的函数建议使用内联。
- 递归函数无法使用内联方式。
C++ 内存管理
内存的本质是什么? 资源
谁掌管内存资源? 操作系统
我们能做什么? 申请/归还
内存的申请和释放
申请/归还内存资源就是内存管理
申请内存 new
释放内存 delete
new 和 delete 都是运算符
//申请内存
int *p = new int;
//释放内存
delete p;
思考:如何申请和释放块内存呢?
int *arr = new int[10]; // 申请块内存
delete []arr; // 释放块内存
内存管理其他方式
申请内存不一定成功
不一定成功,所以程序中要有判断是否为空指针。
int *p = new int[1000];
if(NULL == p)
{
//内存分配失败
}
释放内存注意事项
//普通内存示例
int *p = new int;
if( NULL == p )
{
//内存分配失败
//异常处理
}
delete p;
p = NULL;
//块内存示例
int *p = new int[1000];
if( NULL == p )
{
//内存分配失败
//异常处理
}
delete []p;
p = NULL;
小总结
- 使用new申请内存, 使用delete释放内存。
- 申请内存需要判断是否成功, 释放内存需要设空指针。
…(img-xuurvIn1-1618625434368)]
申请内存不一定成功
不一定成功,所以程序中要有判断是否为空指针。
int *p = new int[1000];
if(NULL == p)
{
//内存分配失败
}
释放内存注意事项
//普通内存示例
int *p = new int;
if( NULL == p )
{
//内存分配失败
//异常处理
}
delete p;
p = NULL;
//块内存示例
int *p = new int[1000];
if( NULL == p )
{
//内存分配失败
//异常处理
}
delete []p;
p = NULL;
小总结
- 使用new申请内存, 使用delete释放内存。
- 申请内存需要判断是否成功, 释放内存需要设空指针。
- new与delete配套使用。