- 引用
定义一个引用,并将其初始化为引用某个变量。
类型名 & 引用名 = 变量名
int n = 4;
int & r = n;
某个变量的引用,等价于这个变量,相当于这个变量的别名(r与n就是一回事)。
int n = 4;
int & r = n;
r = 4;
cout << r; //输出4
cout << n; //输出4
n = 5;
cout << r; //输出5
定义引用时一定要将其初始化成引用某个变量。
初始化后,它就一直引用该变量,不会再引用别的变量了。
引用只能引用变量,不能引用常量和表达式
double a = 4, b = 5;
double & r1 = a;
double & r2 = r1; //r2也引用a
r2 = 10;
cout << a << endl; //输出10
r1 = b; //r1并没有引用b
cout << a <<endl; //输出5
C语言,如何编写交换两个整型变量值的函数
void swap(int a, int b)
{
int tmp;
tmp = a; a = b; b = tmp;
}
int n1, n2;
swap(n1,n2); //n1,n2的值不会被交换,形参的改变不会影响实参
void swap(int * a, int * b)
{
int tmp;
tmp = * a; * a = * b; *b = tmp;
}
int n1, n2;
swap(&n1, &n2); //n1,n2的值会被交换
有了C++的引用
void swap(int & a, int & b)
{
int tmp;
tmp = a; a = b; b = tmp;
}
int n1, n2;
swap(n1, n2); //n1,n2的值会被交换
引用作为函数的返回值
int n = 4;
int & SetValue() { return n ;} //返回值为引用类型,引用变量n
int main()
{
SetValue() = 40; //函数赋值写在等式左侧,等价对n进行赋值
cout << n;
return 0;
}
常引用
定义引用时,前面加上const关键字,即为常引用
int n;
const int & r = n;
r的类型是 const int &
不能通过常引用去修改其引用的内容
int n = 100;
const int &r = n;
r = 200; //编译错
n = 300; //没问题
常引用和非常引用的转换
const T & 和 T & 是不同的类型!!!
T & 类型的引用或T类型的变量可以用来初始化 const T & 类型的引用。
const T类型的常变量和 const T &类型的引用不能用来初始化 T & 类型的引用,除非进行强制类型转换。
2.const关键字用法
定义常量,C++以后建议用const定义常量少用define,const是有类型的便于类型检查
const int MAX_VAL = 23; //整型常量
const double Pi = 3.14; //浮点型常量
const char *SCHOOL_NAME = “Peking University”; //字符串指针型常量
定义常量指针
不可以通过常量指针去修改其指向内容
int n,m;
const int *p = & n;
*p = 5; //编译出错
n = 4; //可以
p = &m; //可以,常量指针的指向可以变换
不可以把常量指针赋值给非常量指针,反过来可以
const int *p1; int *p2;
p1 = p2; //ok
p2 = p1; //error
p2 = (int *)p1; //ok,强制类型转换
函数参数为常量指针时,可避免内部不小心改变参数指针所指地方的内容
void MyPrintf(const char * p)
{ strcpy(p, “this”); //编译出错
printf(“%s”,p); //ok
}
不能通过常引用修改其引用的变量
int n;
const int & r = n;
r = 5; //error
n = 4; //ok
3.动态内存分配
用new运算符实现动态内存分配
第一种用法,分配一个变量:
P = new T;
T是任意类型名,P是类型为T *的指针。
动态分配出一片大小为sizeof(T)字节的内存空间,并将该内存空间的起始地址赋值给P。
int *pn;
pn = new int;
*pn = 5;
第二种用法,分配一个数组:
P = new T[N]
T为任意类型名,P是类型为 T *的指针,N要分配数组元素的个数,可以是整型表达式。
动态分配出一片大小为N*sizeof(T)字节的内存空间,并将该内存空间的起始地址赋值给P.
int * pn;
int i = 5;
pn = new int[i*50];
pn[0] = 20;
new运算符的返回值类型
new T;
new T[n];
这两个表达式的返回值类型都是 T *;
int *p = new int;
用“new”动态分配内存空间,一定要用“delete”运算符释放
delete指针; //该指针必须指向new出来的空间
int *pn;
pn = new int;
*pn = 5;
delete pn;
delete pn; //异常,一片空间不能被释放两次
用“delete”释放动态分配的数组,要加“[]”
delete [] 指针; //该指针必须指向new出来的数组
int * pn;
int i = 5;
pn = new int[i*50];
delete [] pn;
4.内联函数、函数重载和函数缺省参数
内联函数
函数调用是有时间开销的(生成一系列指令,将参数调入栈,返回地址调入栈,执行完成从栈中取出返回地址返回调用处)。如果函数本身只有几条语句,执行非常快,而且函数被反复执行很多次,相比之下调用函数所产生的这个开销就会显得比较大。
为了减少函数的开销,引入了内联函数机制。编译器处理对内联函数的调用语句时,是将整个函数的代码插入到调用语句处,而不产生调用函数的语句。
在函数定义前面加“inline”关键字,即可定义内联函数
inline int Max(int a, int b)
{
if(a>b) return a;
return b;
}
函数重载(C语言不行)
一个或多个函数,名字相同,然而参数个数或参数类型不同,这叫做函数的重载。
以下三个函数是重载关系
int Max(double f1, double f2) { };
int Max(int n1, int n2) { };
int Max(int n1, int n2, int n3) { };
函数重载使得函数命名变得简单
编译器根据调用语句中的实参的个数和类型判断应该调用哪个函数
函数缺省参数
C++中,定义函数的时候可以让最右边的连续若干个参数有缺省值,那么调用函数时候,若相应位置不写参数,参数就是缺省值。
void func( int x1, int x2 = 2, int x3 = 3){} //最右边的两个参数有缺省值
func(10); //等效于func(10,2,3)
func(10,8); //等效于func(10,8,3)
func(10, ,8); //不行,只能最右边的连续若干个参数缺省
函数参数可缺省的目的在于提高程序的可扩充性
即如果某个写好的函数要添加新的参数,而原先调用该函数的语句,未必需要使用新增的参数,那么为了避免对原先那些函数调用语句的修改,就可以使用缺省参数。