十 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 什么是类?
类是将多个对象的共性提取出来定义的一种新的数据类型,是对 对象的属性和行为的抽象描述。