十、C++的引用(Reference)
1、定义
2、常引用
… …
3、引用型函数参数
1)将引用用于函数的形参,可以直接修改实参变量的值,同时减小函数调用的开销;
2)引用参数有可能意外修改实参变量的值,如果不希望修改实参本身,可以将形参定义为常引用,提高传参效率的同时还可以接收常量型的实参;
4、引用型函数返回值
1)可以将函数的返回值声明为引用,避免函数返回值所带来的内存开销;
2)如果一个返回类型被声明为引用,那么该函数返回值可能是一个左值;
3)为了避免在函数的外部修改引用的目标变量,可以返回常引用;
注意:
不要从函数中返回局部变量的引用,因为所引用的目标变量内存会在函数调用结束以后被释放,可以返回成员变量、静态变量、全局变量的引用。
5、引用和指针(了解)
1)引用的本质就是指针
int i = 100;
int& ri = i;
int* const pi = &i;
2)指针可以不做初始化,其指向的目标也可以在初始化以后再修改(指针常量例外);而引用必须初始化,一旦初始化其引用目标不能再做修改;(重点)
eg:
int a = 3, b = 5;
int *p = &a; // p指向a
p = &b; // p指向b
------------------
int& r; // error
int& r = a;
r = b; // 不是修改引用目标而是将b赋值给a
3)可以定义指针的指针(二级指针),但是不能定义引用的指针。
eg:
int a = 100;
int* p = &a;
int** pp = &p; // ok, 二级指针
------------------
int& r = a;
int&* pr = &r; // error
4)可以定义指针的引用(指针的别名),但是不能定义引用的引用。
eg:
int a = 100;
int *p = a;
int* &rp = p; // ok
------------------
int& r = a;
int&& rr = r; // error, //在C++中称为右值引用
5)可以定义指针数组,但是不能定义引用数组
int a = 1, b = 2, c = 3;
int* parr[3] = {&a, &b, &c}; // ok
int& rarr[3] = {a, b, c}; // error
6)可以定义数组的引用(数组的别名)
int arr[3] = {1, 2, 3};
int (&rarr)[3] = arr; // ok
7)和函数指针一样,也可以定义函数的引用,其语法特性和函数指针一致。
void func(int a, double d) {}
int main(void) {
// 函数指针
void (*pfunc)(int, double) = func;
pfunc(10, 3.14);
// 函数的引用(函数的别名)
void (&rfunc)(int, double) = func;
rfunc(10, 3.14);
}
十一、类型转换
1、隐式类型转换
char c = 'A';
int i = c; // 隐式
void foo(int i) {}
foo(c); // 隐式
int fun(void) {
char c = 'A';
return c;
}
2、C++兼容C语言显示类型转换(强制类型转换)
int* p = (int*)malloc(4); // 强制类型转换
char c = 'A';
int i = (int)c; // 强制类型转换
int i = int(c); // C++风格的强制转换
3、C++增加了四种操作符形式显示类型转换
1)静态类型转换
语法:
目标类型变量 = static_cast<目标类型>(源类型变量);
适用场景:
主要用于将void*转换为其它类型的指针;
eg:
int a = 100;
void* pv = &a;
//int* pi = pv;//不能隐式转换,只能显示转换
int* pi = static_cast<int*>(pv);
2)动态类型转换
语法:
目标类型变量 = dynamic_cast<目标类型>(源类型变量);
3)常类型转换
语法:
目标类型变量 = const_cast<目标类型>(源类型变量);
适用场景:
主要用于去除一个指针或引用的常属性。
eg:
const int a = 10;
const int* pa = &a;
*pa = 20; // error
int* p2 = const_cast<int*>(pa);
*p2 = 20; // ok
4)重解释类型转换
语法:
目标类型变量 = reinterpret_cast<目标类型>(源类型变量)
interpret - - - - - v.解释/ in’tә:prit /
适用场景:
–> 在指针和整形数之间的转换
–> 任意类型的指针或引用之间转换
eg:物理内存0x12345678存放一个数据100;
*((int*)0x12345678) = 100;
int* p = reinterpret_cast<int*>(0x12345678);
*p = 100;
小结:C++之父给C程序建议
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)少用联合体、强制转换
6)尽量用string类型表示字符串,少用C风格char*
十二、类和对象
1、什么是对象 ?
万物皆对象,任何一种事物都可以看做是对象。
2、如何描述对象 ?
通过对象的属性(名词、形容词、数量词)和行为(动词)来描述对象。
eg:
冰箱属性:品牌、容量、颜色、功耗…
冰箱行为:冷藏、冷冻、装东西…
3、面向对象的程序设计
对自然世界中对象的管擦引入到编程实践的一种理念和方法,这种方法称为:“数据抽象”;即在描述对象时把细节东西剥离出去,只考虑一般性、有规律性的和统一性的东西。
eg:描述学生对象
学生属性:姓名、年龄、学号
学生行为:吃饭、睡觉、学习
4、什么是类 ?
类将多个对象的共性提取出来定义的一种新的数据类型,是对对象属性和行为的抽象描述。
注:以后可以把struct结构体称为类;