C++const、引用、内联、动态内存分配
const关键字
C++中const修饰的是一个常量
- const常量位于符号表中,正常情况下内存不会为其分配内存空间
- 使用常量的时候从符号表中取值
- 如果对const常量进行取地址操作,则编译器会为其分配一块空间,但是它本身不会使用
define回顾
定义常量 | 宏常量 | 建议用const进行替换 |
---|---|---|
定义函数 | 宏函数 | 建议用内联函数进行替换 |
define与const的区别
- define是预处理的处理,类型完全替换,会在程序中有多个备份
- const是编译的时候处理,会进行变量的类型和作用域检测,只在符号表中有一个备份
引用
引用是空间的别名
int a = 10;
int &b = a; //a和b代表同一块空间
使用引用的时候必须要进行初始化
使用引用进行数据交换
引用可以在一定程度上替换指针
// 利用引用进行数交换
void mySwap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;// 利用引用进行数交换
}
使用引用进行函数传参
void printS(Student *ps);
void printS(Student &rs)
{
re.结构体成员
}
函数返回值为引用
注意:不能返回局部变量的引用,可以返回静态变量或者全局变量的引用
- 使用普通变量接收返回值,接收到变量的值,而不是变量空间
- 使用引用接收返回值,接收到的是变量的空间(引用)
- 如果函数返回值为引用,则可以作为左值使用
func() = 200;
int &func() //函数的返回值是int &引用
{
static int sa = 0; //静态变量
sa++;
printf ("func:sa = %d\n", sa);
return sa;
}
int main()
{
// 不接收返回值
func();//1
// 使用普通变量接收返回值,接收到变量的值,而不是变量空间
int a = func();//2
cout << "a = " << a << endl;
a = 50;
func(); //3
// 使用引用接收返回值,接收到的是变量的空间(引用)
int &a2 = func(); //4
a2 = 100;
func(); //101
// 如果函数返回值为引用,则可以作为左值使用
func() = 200;//200
func(); //201
return 0;
}
指针引用
struct Student
{
int id;
};
void func(Student **ps)
{
//*ps是结构体指针
*ps = (Student *)malloc(sizeof(Student) / sizeof(char));
(*ps)->id = 40;
}
void func(Student* &rps)
{
rps = (Student *)malloc(sizeof(Student) / sizeof(char));
rps->id = 20;
}
int main()
{
Student *ps = NULL;
func(&ps);
cout << "id = " << ps->id << endl;
func(ps);
cout << "id = " << ps->id << endl;
getchar();
}
常引用
内联函数
- 内联函数: 在函数定义前加上inline关键字,在函数声明前加上inline是无效的
- 内联函数在函数调用的时候用函数定义去替换,避免了函数的入栈,出栈,跳转等开销
- 内联函数时在编译的时候处理的,**宏函数是在预处理的时候进行处理的 **
注意:
- 内联是一种请求,有可能内联不成功
- 程序运行的时候,内联函数时没有代码空间的,在编译的时候已经替换完了
- 因此,不能对内联函数进行取地址操作 ===> 不能作为回调函数 ===> 不可以调试
- 内联函数的函数体不要太大,不要超过5行
- 不要有任何形式的循环语句
- 不要有复杂的判断语句
- 内联的实现:内联函数存放在符号表中,实际调用的时候从符号表中取值
#define MAX(a, b) a>b ? a:b
#define ADD(a, b) ((a)+(b))
动态内存分配
C中动态内存分配
- malloc()和free()
- 两者属于库函数
C++中动态内存分配
- new和delete
- 两者属于运算符
new申请单个变量空间
int main()
{
// C malloc() free()
int *p1 = (int *)malloc(sizeof(int) / sizeof(char));
if (NULL == p1)
{
cout << "malloc申请失败" << endl;
return -1;
}
*p1 = 100;
cout << "*p1 = " << *p1 << endl;
free(p1);
// C++ new delete运算符
int *p2 = new int; // 类型名* 变量名 = new 类型名(初始值)
if (NULL == p2)
{
cout << "new申请失败" << endl;
return -1;
}
*p2 = 10;
cout << "*p2 = " << *p2 << endl;
delete p2;
// new在申请空间的时候可以对空间进行初始化
char *pc = new char('A');
cout << "c = " << *pc << endl;
delete pc;
//
getchar();
}
new申请数组
int main()
{
// C malloc() free()
// int a[3][4];
int *p1 = (int *)malloc(sizeof(int) / sizeof(char) * 10);
if (NULL == p1)
{
cout << "malloc申请失败" << endl;
return -1;
}
for (int i = 0; i < 10; i++)
{
p1[i] = i;
cout << p1[i] << " ";
}
cout << endl;
free(p1);
// C++ new delete运算符
int *p2 = new int[10]; // 类型名* 变量名 = new 类型名[个数],申请数组的时候不能进行初始化
if (NULL == p2)
{
cout << "new申请失败" << endl;
return -1;
}
for (int i = 0; i < 10; i++)
{
p2[i] = i;
cout << p2[i] << " ";
}
// delete 释放数组的时候一定要[] 否则仅释放第一个元素,造成内存泄露
delete[] p2;
getchar();
}
new申请连续空间上的多维数组
// new申请连续空间上的多维数组
int main()
{
// C
//int a[3][4],
//(*pa)[4]是指针,指向一个二维数组的指针,行指针,[4]说明每行有4个元素,[0]代表第一列的下标
int(*p1)[4] = (int(*)[4])malloc(sizeof(int) / sizeof(char) * 12);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
pa[i][j] = i * 4 + j;
cout << p1[i][j] << " ";
}
cout << endl;
}
free(pa);
// C++
int(*p2)[4] = new int[3][4];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
pa[i][j] = i * 4 + j;
cout << pa[i][j] << " ";
}
cout << endl;
}
delete[] p2;
getchar();
return 0;
}
new申请非连续空间上的多维数组
// 动态申请内存 不连续多维数组
int main()
{
// C
//int a[3][4],
//(**pa)是二级指针,指向一个指针数组,每个指针数组元素指向一个int数组[4]
int **pa = new int*[3];
for (int i = 0; i < 3; i++)
{
pa[i] = new int[4];
}
for (int i = 0; i < 3; i++)
{
// 先释放掉int数组的空间
delete[] pa[i];
}
// 再释放掉指针数组的空间
delete[] pa;
return 0;
}