引用
引用的概念
- 以下写法定义了一个引用,并将其初始化为引用某个变量
类型名 & 引用名 = 某变量名;
int n = 4;
int & r = n; //r引用了n,r的类型是:int &
- 某个变量的引用,等价于这个变量,相当于该变量的一个别名。
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
引用作为函数的返回值
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 = 200; //没问题
常引用和非常引用的转换
const T & 和 T & 是不同的类型!!!
- T & 类型的引用或T类型的变量可以用来初始化const T & 类型的引用
- const T 类型的常变量和 const T &类型的引用则不能用来初始化T &类型的引用,除非进行强制类型转换。
const关键字
用法如下:
1)定义常量
const int a = 3;
2)定义常量指针
- 不能通过常量指针修改其指向的内容
int n, m;
const int * p = & n;
* p = 5; //编译出错(不能通过常量指针修改其指向的内容)
n = 4; //ok
p = & m; //ok,常量指针的指向可以改变(底层const)
- 不能把常量指针赋值给非常量指针,反过来可以
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
}
3)定义常引用
- 不能通过常引用修改其引用的变量
int n;
const int & r = n;
r = 5; //error
n = 4; //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:要数组元素的个数,可以是整型表达式
动态分配出一片大小为sizeof(T) * N字节的内存空间,并且将该内存空间的起始地址赋值给P。比如:
delete运算符释放动态分配的内存
- 用“new”动态分配的内存空间,一定要用 “delete”运算符进行释放
语法:delete 指针;//该指针必须指向new出来的空间
int * p = new int;
* p = 5;
delete p;
delete p; //导致异常,一片空间不能被delete多次
delete运算符释放动态分配的数组
- 用“delete”释放动态分配的数组,要加“[ ]”
语法: delete [ ] 指针;//该指针必须指向new出来的空间
int * p = new int[20];
p[0] = 1;
delete [ ] p;