下面的写法定义了一个
引用
,并将其初始化为引用某哥变量。
类型名 & 引用名 = 某变量名;
某个变量的引用,等价于这个变量,相当于该变量的一个别名
// 模板
int = 4;
int & r = n; // r引用了n,r的类型是int &
//案例
int n = 7;
int & r = n;
r = 4;
cout << r; //输出4
cout << n; //输出4
注意事项:
1、定义引用时一定要将其初始化
成引用某个变量
。
2、初始化后,它就一直引用该变量。
3、引用只能
引用变量
,不能引用常量。
案例如下:
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的值会被交换
// 引用传递
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;}
int main()
{
SetValue() = 40;
cout << n;
return 0;
}
// 输出:40
定义引用时,前面加const关键字,即为常引用
int n;
const int & r = n;
r 的类型是const int &
常引用的特点
不能通过常引用去修改其引用的内容:
int n = 100;
const int & r = n;
r = 200; // 编译报错
n = 300; // 编译没问题
const type & 和 type & 是不同类型!!!
1、type &类型的引用或type类型的变量可以用来初始化const type & 类型的引用
2、const type 类型的常变量和const type & 类型的引用则不能用来初始化type 类型的引用,除非进行强制类型转化
。
1)定义常量
const int MAX_VAL = 23;
const double Pi = 3.14;
// 常量字符串类型的指针
const char * SCHOOL_NAME = "Peking University";
2)常量指针
注意事项1
:不可通过常量指针修改其指向的内容,但常量指针的指向可以发生变化
int n,m;
const int * p = &n;
* p = 5; // 编译出错
n = 4; // 编译OK
p = &m; // 编译OK,常量指针的指向可以发生变化
注意事项2
:不能把常量指针赋值给非常量指针,反过来可以(如下案例)
const int * p1; // 常量指针
int * p2; // 指针
p1 = p2; // 编译OK
p2 = p1; // 编译error
p2 = (int *)p1; // 编译OK,强制类型转换
注意事项3
:函数参数为常量指针时,可避免函数内部不小心改变参数指针所指地方的内容。
void MyPrintf(const char * p)
{
// 函数strcpy第一个参数是char型,p是const char型
strcpy(p, "this"); //编译error
printf("%s", p); //OK
}
用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 * 20]; // i✖️20个元素 pn[0] = 20; pn[100] = 30; // 编译OK。运行时error数组越界
new T; new T[n];
这两个表达式返回值的类型都是
T *
int * p = new int;
1、用“new” 动态分配的内存空间,一定要“delete”运算符进行释放
delete 指针;
// 该指针必须
执行new出来的空间int * p = new int; * p = 5; delete p; delete p; // error,一片空间不能被delete多次
2、用“delete”释放动态分配的数组,要加“[]”
delete [] 指针;
// 该指针必须
执行new出来的空间int * p = new int[20]; p[0] = 1; delete [] p;
内联函数
的调用语句时,是将整个函数的代码插入到调用语句处,而不会产生调用函数的语句。一般只将那些短小的、频繁调用的函数声明为内联函数。
在函数定义前面加
“inline”
关键字,即可定义内联函数inline int Max(int a, int b) {if(a > b) return a; return b; }
如在在主函数中调用内联函数k = Max(n1, n2);
,编译器会将其变成如下形式:
if (n1, n2)
tmp = n1;
else tmp = n2;
k = tmp;
函数重载
:一个或多个函数,名字相同,然而参数个数
或参数类型
不相同,这叫函数的重载。
以下三个函数是重载关系:int Max(double f1, double f2) { }; int Max(int n1, int n2) { }; int Max(int n1, int n2, int n3) {};
作用:
- 函数重载使得函数命名变得简单。
- 编译器根据调用语句中的实参的个数和类型判断应该调用哪个函数。
(1) int Max(double f1, double f2) { }; (2) int Max(int n1, int n2) { }; (3) int Max(int n1, int n2, int n3) {}; Max(3.4, 2.5); // 调用(1) Max(2,4); // 调用(2) Max(1, 2, 3); // 调用(3) Max(3, 2.4); // error,二义性
C++中,定义函数的时候可以让最右边的连续若干个参数有缺省值,那么调用函数的时候,若相应位置不写参数,参数就是缺省值。
void func(int x1, int x2 = 2, int 3 = 3) {}
func(10); // 等效于func(10, 2, 3)
func(10, 8); // 等效于func(10, 8, 3)
func(10, , 8); // error,只能最右边的连续若干个参数缺省