目录
一.引用
1.定义
int a=0;
int &b=a;
b就是a的新名称,并不开辟新空间
可以看出两个变量所指向的地址是相同的
注意:
1.引用在定义时必须需要初始化
2.一个变量可以有多个引用
3.引用一旦引用了一个实体,就不能再引用其他实体
int a=0;
int &b=a;
int c=10;
b=c;//1.将b变成c的引用?x
//2.将c的值赋b?对
2.使用场景
1.引用做参数(传引用)
void swap(int &r1,int &r2)
{
int tmp=r1;
r1=r2;
r2=tmp;
}
r1,r2即是引用做参数,r1,r2可以认为是所传参数本身,直接对所传参数进行操作,省去了指针在传参时的繁琐操作
优点:
1.在有些场景下,可以提高性能(大对象+深拷贝对象
2.形参的改变可以直接改变实参
2.做返回值
int& Ad(int a,int b)
{
static c=a+b;
return c;
}
注意看:如果出了作用域,返回对象还在,才可引用返回(所以c有static修饰)!!!
下面进行错误示范
int& Ad(int a,int b)
{
int c=a+b;
return c;//返回c的引用
}
当前代码存在的问题:
1。存在非法访问,因为Add的返回值是c的引用,在Add销毁了之后回去访问c的位置空间
2。如果Add栈帧销毁,清理空间,取的c的值就是随机值,具体看编译器的处理 错误用法
优点
int& At(int i)
{
static int a[100];
return a[i];
}
int main ()
{
At(1)=1;//可以直接改变函数返回值
return 0;
}
3.使用权限问题
//权限的放大
const int a=10;
int& b=a
a加了const后不可改变值,引用时不可直接引用,会有权限的放大
const int a=10;
const int& b=a;//没问题 权限不变
int c=10;
const int& d=c;//权限的缩小是可以的
所以权限只能不变或者缩小
考虑权限问题,建议在只读数据时加上const
注意的细节:
临时变量具有常性,临时变量是右值,不可改变
如以下两种情况
1.临时变量做返回值时不可改变
int At(int i)
{
static int a[100];
return a[i];
}
int main()
{At(1)=1;//临时变量具有常性,临时变量是右值,不可改变
return 0;
}
2.类型转换时转换的值是作为临时变量
float a=1.1;
int& b=a;//进行类型转换时a存在临时变量中,临时变量具有常性,临时变量是右值 不能修改,要加const
const int& c=a;
二.内联函数
inline int Add(int a,int b)
{int c=a+b;
return c;
}
一般调用函数,需要建立栈帧,栈帧中要保存一些寄存器,结束后又要恢复,会有损耗 内联函数可以对于频繁调用的小函数进行优化,优化方法类似宏
//宏
#define Add(x,y) (x+y)
在实现内联函数时,编译器会将内联函数进行类似宏替换的操作
使用inline后,编译器从调函数(call)变成mov add 直接调寄存器在主函数的栈帧中进行操作,不再建立函数栈帧进行运算。
三.auto
自动推导变量类型
auto a=0;
打印变量类型的函数。typeid(变量).name()
cout<<typeid(a).name()<<endl;
实际使用场景:
有长类型命名的变量用auto方便使用
struct STListLine*p=NULL;
auto new=*p;
范围for(语法糖)
for(auto e:array)//e前面可以写清楚类型
{
e++;//局部变量,对array没影响
}
注意:e:后面必须是数组
如
void Print(int a[])
{for(auto e:a)//会报错
{cout<<e<<endl;
}
}
因为数组在传参的时候会退化成int*,而不是int []
四.nullptr
c++11后推荐使用nullptr代替NULL
使用NULL可能会出现问题