变量都是有内存空间的,当它在堆栈区时可以通过指针修改它的值。
本质地址传递;编译器帮忙做了基本地址传递的部分。
int &b = a;=====> int * const b = &a;(实质) b常指针,指向不可以改变。
(本质上:引用是一个常指针)
1)同一个内存块可以取多个别名。
int& b = a;
int& c = a;
2)引用的基本语法:
int a = 10;
int &b = a;(引用)
b = 100;
cout << a << endl; cout << b << endl;
输出的结果都为 100.
3)指针的引用;
int *p = NULL;
int *&p1 = p;
p1 = (int *)malloc(sizeof(int));
4)数组的引用:(两种方式)
1.
typedef int ARR[10];/*建立数组类型*/
int a[10];/*创建一个数组*/;
ARR &p = a;/*对数组的引用*/
p[i] = i;/*对数组的某个元素赋值*/
2.
int (&p1)[10] = a;/*直接建立数组类型,进行引用,并初始化。*/
p1[i] = i; /*对数组的某个元素赋值*/
"注意内容:"
5) 引用没有定义,是一种关系型声明。声明它和原有某一变量(实体)的关系。故而类型与原类型保持一致,且不
分配内存。与被引用的变量有相同的地址
声明引用变量时必须初始化, int& b; //错误
必须确保引用是和一块合法的内存块关联( NULL 不可内存不可引用)。
可以建立数组引用。
6)引用一旦初始化,不能改变。(原因如上:本质)
int &b = a; b = c (这种写法并不是改变b的指向,是将c的值赋给 b; b并没有指向c);
7)(常量引用)const int &b = a; b的值、指向都不能改变。
因为它等同于: const int *const b = &a;(这种写法常用来保护"实参"不受"形参"的改变).
8)C++编译器在编译过程中使用"常指针"作为引用的内部实现,因此引用所占用的空间大小与指针相同。(非官方的说法,但是大家都这么说)
9)
//建立普通变量的引用
int ma = 9;
int &ra = ma; //建立引用。 ===》 int *const ra = &ma; 即 ra = &ma;
ra = 88; //通过引用修改变量的值。这步是编译器帮忙进行解引用,然后赋值的。
//建立对指针的引用
int *p2 = NULL;
int *&mp2 = p2; //建立引用。===》 int ** const mp2 = &p2;
mp2 = (int *)malloc(sizeof(int)); //通过引用给指针p2分配空间。也就是给p2重新赋值,让他重新指向。
//建立对数组的引用
typedef int Arr[10]; /*建立数组类型 */ Arr a; //建立一个普通数组
Arr &p3 = a; //建立引用 ===》 Arr * const p3 = &a;
p3[3] = 10; //对数组的第四个元素赋值。
1)单独定义引用时,必须初始化;说明它很像一个常量,因为常亮在定义时也必须初始化(const int a = 5)。
2) 普通引用有自己的空间。(在32位平台下占4个字节。)但是引用变量的地址和初始化它的变量是同一块地址。
int &a = b; a 和 b 的地址相同。()
struct teacher {int a; char b; int &d; double &c; }; 这个结构体所占内存为16;
struct teacher {int a; char b; }; 这个结构体所占内存为8;
3)引用的本质是一个常量指针。
1)引用做参数不需要初始化
2)不能返回局部变量引用;(和返回局部指针变量原因一样)。
3)引用做返回值。(可以做左值和右值)
4)指针的引用。
5)(常量引用):const 对引用的使用(如上:)。const 引用的值不能修改(主要用在函数的形参:不想用形参改变实参的值)
6)"函数的返回值当左值需要返回引用。"
1)使用class关键字
2)类里面可以放变量、函数。
3)public: 访问权限
C++中使用(既有宏函数的效率,又没有普通函数的开销;可以像普通函数那样,进行参数,返回值类型的安全检查,又可以
作为成员函数。 在C++中,定义内联函数,只是对编译器的一个建议,并不一定会成为内联函数。
(内联函数的语法)
1)普通函数; inline void func(int x){ return; }但是必须注意必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待。
2)要求:不能存在任何形式的循环语句;不能存在过多的条件判断语句; 函数体不能过于庞大; 不能对函数进行取址操作
1) #define ADD(X, Y) X+Y
int main() {2)副作用很多:无脑替换,不检查语法;没有作用域,从定义开始到文件结束
1)默认参数:int func(int x = 10,int y = 20);此时形参的赋值就是默认参数,当函数调用不传参数时,就将使用默认参数。。
2)注意:
int func051(int x, int y = 0, int z = 0);//函数的默认参数从左向右,如果一个参数设置了默认参数,那么这个参数之后的参数都必须设置默认参数。
函数的声明和函数的定义不能同时写默认参数,("即使默认参数相同也不行")编译器不知道该选择哪套
3)占位参数:
"函数的占位参数也是参数,必须要给个值,只是函数内部用不了而已. " int func(int , int y);或 int func(int ,int y = 3);
当占位参数与默认参数结合时:int func(int =5, int y);"erro" ;这种写法,int (int y, int =30);占位参数只能写在最后一个形参的位置。
而且可以不给它传参。因为它有了默认参数。
1)函数重载的条件:
"可以作为条件的:"
同一个作用域:函数名相同,形参的个数、形参的类型、形参的类型顺序不同;
用 const 进行修饰的函数也可以进行重载。 非 const 对象优先调用非 const 函数。
const 对象只能调用 const 函数,const 函数只能调用 const 函数,可以被 const 函数和非 const 函数调用。
注意:不可以作为条件的
"函数的返回值不能作为函数重载的条件"
"函数重载和默认参数不能同时出现";函数重载碰到默认参数,那么要考虑是否会出现函数调用二义性(会报错,编译通不过)。
2)重载函数的调用:
正常调用:"函数调用正常匹配函数形参(可以找到)。"
隐式类型转换后调用:"当找不到匹配的形参时,编译器会进行隐式转换,仍然找不到后会进行报错。(如下)"
void func(char b); int main(){ int a = 3; func(a);} 此时就会进行隐式转换,因为与ASCII码匹配。
3)函数重载的原理:
编译器为了实现函数重载,在编译的时候做了一些优化,用不同的类型来修饰不同的函数名。
如:void func(){}
void func(int a){}
void func(int a,char b){}
上述三个函数编译完后:生成的函数名为:_z4funcv "v代表void,无参数"
_z4funci "i代表参数为int类型"
_z4funcic "i代表第一个参数为int类型,第二个参数为char 类型"
本页共95段,3359个字符,7092 Byte(字节)