C++02
指针和引用
引用:某一个变量的别名。对引用的操作和对变量的操作完全一样。
基本数据类型引用:
#include<iostream>` `using namespace std;` `int main(){` `int a=3;` `int &b=a;`//引用必须初始化,否则编译时报错 `b=10;` `cout<<a<<endl;` `return 0;` `}
输出结果:10
a的别名是b。对b操作就是对a操作。
结构体类型的引用:
#include<iostream>` `using namespace std;` `typedef struct{` `int x;` `int y;` `}GOT7;` `int main(){` `GOT7 got7;` `GOT7 &Got=got7;` `Got.x=10;` `Got.y=11;` `cout<<got7.x<<" "<<got7.y<<endl;` `return 0;` `}
输出结果: 10 11
Got是got7的别名,对Got操作就是对got7操作。
指针类型的引用:
语法:*类型 &指针引用名=指针;
#include<iostream>` `using namespace std;` `int main(){` `int a=10;` `int *p=&a;` `int *&q=p;` `*q=20;` `cout<<a<<endl;` `return 0;` `}
输出结果:20
指针p指向a;为p起一个别名q,对q操作就是对p操作,对p操作就是对a操作。
引用作函数参数
#include<iostream>
using namespace std;
void fun(int &a,int &b){
int c=0;
c=a;
a=b;
b=c;
cout<<a;
cout<<b;
}
int main(){
int x=10;
int y=20;
fun(x,y);
return 0;
}
输出结果:20 10
define VS const
const与基本数据类型
const int x=2;
//变量x成为了常量,x的值无法再更改。
const与指针类型
const int *p=null;
①
const 只对*p有作用,对变量p没有作用;
无法通过*p来修改x的值,但是变量p还可以指向其他变量的地址;
#include<iostream>` `using namespace std;` `int main(){` `int x=2;` `int y=1;` `int const *p=&x; p=&y; cout<<*p<<endl;` `cout<<p<<endl;` `return 0;` `}
输出结果:1(换行)0x6bfee4
输出p是输出了p指向变量的地址,输出*p是p指向的变量的值。
int const *p=null;
②
const修饰的p只能指向一个变量地址。
int *const p=null;
③
p不能指向其他其他变量的值,而且也无法通过*p修改变量x的值。
const int *const p=null;
④
int const* const p=null;
⑤
const与引用
y是x的一个别名,由const修饰的y之后,只能通过对x操作来修改x的值,无法通过y来修改x的值。
两种写法对比:(权限限制)
const int x=3; int *y=&x;
x是一个常量,用一个可变的指针指向一个常量,则很有可能通过指针修改常量的值,计算机是不允许这种有风险的操作,所以这种写法是错误的。
int x=3;const int *y=&x;
x是一个变量,(可以看作,具有读写的权利),用一个由const修饰的指针y指向下x,y只能指向x一个变量,(可以看作,const修饰下,y只有读的权利,没有写的权利了)然后可以直接用对x操作来修改x的值。但是*y就无法修改x的值。这种在计算机下是可以行的。用一个权限小的来限定权限大的。
const与define
#define X 3
const int x=3;
从效果上来讲是一样的,都是定义一个X值为3的常量。但是在编译的过程中,define由于是宏定义,就不再检查错误。而const在编译的时候就需要检查错误。
所以推荐使用const来定义一个常量。
const在函数中的使用
const的使用可以保证传入函数中变量,不会因为函数的误操作而修改原有值。
函数默认值和函数重载
函数参数默认值特性
有默认参数值的参数必须写在参数表的最右端。
void fun(int i,int j=0,int k=10);是正确的。
void fun(int i,int j=5,int k);是错误的。
声明的时候可以写参数默认值,定义的时候最建议不要写。
#include<iostream>
using namespace std;
void fun(int i,int j=10,int k=11){
cout<<i<<endl;
cout<<j<<endl;
cout<<k<<endl;
}
int main(){
fun(20);
cout<<"========"<<endl;
fun(20,30);
cout<<"========"<<endl;
fun(20,30,40);
return 0;
}
输出结果:20 10 11;20 30 11; 20 30 40
没有实参就用默认值,有实参就去覆盖默认值。
函数重载(提高效率)
在相同的作用域内,用同一函数名定义的多个函数,参数类型和参数个数不同。
遇到函数名称相同的情况,计算机通过函数名称加参数个数参数类型来判断是使用哪个函数。
内联函数
编译时将函数体代码和实参代替函数调用语句。内联函数只是一种编译方式。
关键字:inline。
为什么并不是所有的函数都使用内敛函数?虽然他效率高,运行速度快,但是是有条件的。
内联函数是建议性的,由编译器决定是不是采用内敛函数。
内联函数只能是逻辑简单,调用频繁的函数建议使用内联。
递归函数无法使用内敛方式。
练习:
#include <iostream>
using namespace std;
/**
*函数功能:返回a和b的最大值
*a和b是两个整数
*/
int getMax(int a, int b)
{
return a > b ? a : b;
}
/**
* 函数功能:返回数组中的最大值
* arr:整型数组
* count:数组长度
* 该函数是对上面函数的重载
*/
int getMax(arr,count)
{
//定义一个变量并获取数组的第一个元素
int temp=arr[0];
for(int i = 1; i < count; i++)
{
//比较变量与下一个元素的大小
if(temp<arr[i])
{
//如果数组中的元素比maxNum大,则获取数组中的值
temp=arr[i];
}
}
return temp;
}
int main(void)
{
//定义int数组并初始化
int numArr[3] = {3, 8, 6};
//自动调用int getMax(int a, int b)
cout << getMax(3, 6) << endl;
int count=3;
//自动调用返回数组中最大值的函数返回数组中的最大值
cout << getMax(numArr, count) << endl;
return 0;
}
//自动调用int getMax(int a, int b)
cout << getMax(3, 6) << endl;
int count=3;
//自动调用返回数组中最大值的函数返回数组中的最大值
cout << getMax(numArr, count) << endl;
return 0;
}
错误原因:在对getMax(int a,int b)
进行重载的时候,即getMax(arr,count)
没有声明arr和count的类型。正确写法应该是:
int getMax(int *arr,int count)
内存管理
什么是内存管理?
内存的本质就是资源,内存是由操作系统掌控的。我们需要向os申请或者归还内存资源。
如何进行内存的申请和释放?
一个或者某一类型的内存申请与释放:
申请内存 new运算符 int *p=new int
;
释放内存 delete运算符 delete p;
申请和释放块内存:
申请块内存:int *arr=new int[10];
释放块内存:delete []arr;
内存操作注意事项:
c语言:申请:malloc 释放 free
运算符配套使用,不要混搭。
申请内存有可能由于内存不够等原因申请失败。
申请内存的时候需要判断是否成功,释放内存需要设空指针。
释放内存注意事项
释放完内存以后,要将指针置为NULL;避免出现同一块内存被重复回收,计算机出现异常。
练习:
在堆中申请100个char类型的内存,拷贝Hello imooc字符串到分配的堆中的内存中,打印字符串,最后释放内存。
#include <string.h>
#include <iostream>
using namespace std;
int main(void)
{
//在堆中申请100个char类型的内存
char *str = new char[100];
//拷贝Hello C++字符串到分配的堆中的内存中
strcpy(str, "Hello imooc");
//打印字符串
cout<<str;
//释放内存
delete []str;
str=NULL;
return 0;
}