十 C++的引用(Reference) 1 2 3 引用型函数参数 1)将引用用于函数的参数,可以修改实参变量的值,同时也能减小函数调用的开销。 2)引用参数有可能意外修饰实参的值,如果不希望修改实参变量本身,可以将其定义为常引用,提高传参效率的同时还可以接收常量型的实参。 4 引用型函数返回值 1)可以将函数返回类型声明为引用,避免函数返回值所带来的开销。 2)一个函数返回类型被声明为引用,那么该函数返回值可以是一个左值。 3)为了避免在函数外部修改引用的目标,可以为该引用附加常属性。 eg: int& foo(void){ static int a = 100; return a; } int main(void) { foo() = 200;//ok } 注:不要返回局部变量的引用,因为所引用的目标内存会在函数返回以后被释放,危险! 但是可以返回成员变量、静态变量、全局变量的引用 //笔试题:引用和指针的区别... 5 引用和指针 1)从C语言角度,引用的本质就是指针,但是在C++中推荐使用引用而不是指针。 eg: double d = 3.14; double& rd = d; double* const pd = &d; rd <=等价=>*pd 2)指针定义可以不做初始化,其目标可以修改(指针常量除外),而引用必须做初始化,而且一旦初始化所引用的目标能再改变。 eg: int a=3,b=5; int* p;//ok,可以不初始化 //int& r;//error p = &a; p = &b; int& r = a; r = b;//不是修改引用的目标,而是对r(a)进行赋值 //后面了解 3)可以定义指针的指针(二级指针),但是不能定义引用的指针 eg: int a = 100; int* p = &a; int** pp = &p; int& r = a; int& * pr = &r;//error int* pr = &r;//ok,是一个普通的指针 4)可以定义指针的引用,但是不能定义引用的引用 eg: int a = 100; int* p = &a; int* & rp = p;//ok,指针的引用 ----------- int& r = a; int&& rr = r;//error,在C++11中称为右值引用 int& r2 = r;//ok,不能称为引用的引用,只是一个普通的引用,相当于给a再起一个别名。 5)可以指针数组,但是不能引用数组 eg: int a=1,b=2,c=3; int* parr[3] = {&a,&b,&c};//指针数组 int& rarr[3] = {a,b,c};//error 6)可以定义数组引用 eg: int arr[3] = {1,2,3}; //rarr称为数组引用,给数组起一个别名 int (&rarr)[3] = arr;//ok arr[0] <-等价-> rarr[0] 7)和函数指针一样,可以定义函数引用,语法和函数指针一致。 eg: void func(int a,int b){...} int main(void){ //定义和使用函数指针 void (*pfunc)(int,int) = func; pfunc(10,20); //定义和使用函数引用 void (&rfunc)(int,int) = func; rfunc(10,20); } ====================================== 十一 类型转换 1 隐式类型转换 eg: char c = 'A'; int n = c;//隐式类型转换 ----------- void foo(int n){..} foo(c);//隐式类型转换 ----------- int foo(void){ char c = 'A'; return c;//隐式类型转换 } 2 强制类型转换 eg: char c = 'A'; int n = (int)c;//C风格的强制转换 int n = int(c);//C++风格的强制转换 3 C++增加了四种操作符形式的显式类型转换 1)静态类型转换 语法: 目标类型变量 = static_cast<目标类型>(源类型变量); 适用场景: 用于将void*转换为其它类型指针。 eg: int a = 100; void* pv = &a;//ok int* pi = pv; //error int* pi = static_cast<int*>(pv);//ok 2)动态类型转换(后面讲) 语法: 目标类型变量 = dynamic_cast<目标类型>(源类型变量); 3)常类型转换 语法: 目标类型变量 = const_cast<目标类型>(源类型变量); 适用场景:用于去除一个指针或引用的常属性 eg: int a = 100; const int* pa = &a; *pa = 200;//error int* pa2 = const_cast<int*>(pa); *pa2 = 200;//ok ------------------- const int& r = a; r = 300;//error int& r2 = const_cast<int&>(r); r2 = 300;//ok 4)重解释类型转换 语法: 目标类型变量 = reinterpret_cast<目标类型>(源类型变量); 适用场景: -->任意类型的指针或引用之间的转换 -->在指针和整型数之间的转换 eg: int addr = 0x12345678; int* p = reinterpret_cast<int*>(0x12345678); *p = 100; ====================== 小结: 1 慎用宏,用const、enum、inline替换 #define PAI 3.14 --》const double PAI = 3.14 #define STATE_SLEEP 0 #define STATE_RUN 1 #define STATE_STOP 2 --》enum STATE{SLEEP,RUN,STOP}; #define max(a,b) ((a)>(b)?(a):(b)) --> inline int max(int a,int b){ return a > b ? a : b; } 2 变量随用随声明同时初始化 3 尽量使用new/delete分配,取代malloc/free 4 少用void*、指针计算、联合体、强制转换 5 尽量使用string表示字符串,少用C中的char*表示的字符串 ==================================== 十二 类和对象//了解 1 什么是对象? 万物皆对象,任何一种事物都可以看做是对象。 2 如何描述对象? 通过对象的属性(名词、数量词、形容词)和行为(动词)描述和表达对象。 3 面向对象的程序设计 对自然世界中对象观察引入到编程实践的一种理念和方法。这种方法称为"数据抽象",即在描述对象时把细节的东西剥离出去,只考虑一般性的,有规律性的和统一性的东西。 4 什么是类? 类是将多个对象的共性提取出来定义的一种新的数据类型,是对 对象的属性和行为的抽象描述。