五、引用
普通引用只能引用左值,常引用既可以引用左值又可以引用右值。普通引用也叫做左值引用;常引用也叫做万能引用;
1、引用型函数返回值
1)可以将函数的返回类型声明为引用,避免函数返回值所带来的内存开销,如果一个函数返回类型声明为引用,那么该函数返回值就是一个左值。2)为了避免在函数外部修改引用的目标变量,可以为该引用附加常属性。
3)不要从函数中返回局部变量的引用,因为所引用的内存会在函数返回以后被释放。
4)可以在函数中返回成员变量、静态变量、全局变量引用
2、引用和指针的区别?(笔试题)
1)引用本质就是指针
double d = 3.14;
double& r = d;//double* const p =&d;
2)指针可以不初始化,其目标可以在初始化以后随意改变(除了指针常量),而引用必须初始化,而且一旦初始化所引用的目标不能再改变。
int a,b;
int* p;//可以不初始化
p = &a;//p指向a
p = &b;//p指向b
==================
int& r;//error,引用不能不初始化
int& r = a;//r引用a
r = b;//将b的值赋值给a
3)可以定义指针的指针(二级指针),但是不能定义
引用的指针。
int a;
int* p = &a;
int** pp = &p;//ok,二级指针
int& r = a;
int&* pr = &r;//error
4)可以定义指针的引用,不能定义引用的引用
int a;
int* p = &a;
int*& rp = p;//ok,指针的引用
int& r = a;
int&& rr = r;//error,C++2011可以叫做右值引用
5)可以定义指针的数组,但是不能定义引用数组。
int a,b,c;
int* parr[3]={&a,&b,&c};//ok
int& rarr[3]={a,b,c};//error
6)可以定义数组引用
int arr[3] = {1,2,3};
int (&r)[3] = arr;//ok
//int &r[3] = arr;//error
7)和函数指针一样,可以定义函数引用,语法相同
void func(int a,int b){
...
}
int main(void){
void (*pfunc)(int,int)=func;
void (&rfunc)(int,int)=func;//函数引用
}
六、C++兼容C的基础上增加了四种操作符形式的类型转换
1)静态类型转换
目标类型变量 = static_cast<目标类型>(源类型变量)
主要用于将void* 转换为其它类型的指针
int a;
void* pv = &a;
int* pn = static_cast<int*>(pv);
double d = 3.14;
double* pd = &d;
//pn = (int*)pd;//ok
pn = static_cast<int*>(pd);//error
2)动态类型转换
目标类型变量 = dynamic_cast<目标类型>(源类型变量)
//后面讲
3)常类型转换
目标类型变量 = const_cast<目标类型>(源类型变量)
主要用于去除一个指针或引用的常属性
const int a = 10;
const int* p = &a;
*p = 20;//error
int *p2 = const_cast<int*>(p)
*p2 = 20;//ok
const int& r = a;
r = 30;//error
int& r2 = const_cast<int&>(r);
r2 = 30;//ok
4)重解释类型转换
#include <iostream>
using namespace std;
int main(void)
{
/*volatile修饰的变量意思是可变的、易变的,
告诉编译器不要做优化处理,使用该变量时,
每次都要从内存中去读取,而不是取寄存器中
的副本*/
const volatile int ci = 100;
int* pci = const_cast<int*>(&ci);
*pci = 200;
cout << "ci=" << ci << endl;
cout << "&ci=" << (void*)&ci << endl;
cout << "*pci=" << *pci << endl;
cout << "pci=" << pci << endl;
return 0;
}