做外贸最好的网站有哪些,深圳网站设计x,wordpress ajax请求,seo上海优化引用
6.1 引用概念 引用不是新定义一个变量#xff0c;而是给已存在变量取了一个别名#xff0c;编译器不会为引用变量开辟内存空间#xff0c;它和它引用的变量共用同一块内存空间。 比如#xff1a;李逵#xff0c;在家称为铁牛#xff0c;江湖上人称而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空间它和它引用的变量共用同一块内存空间。 比如李逵在家称为铁牛江湖上人称黑旋风
typedef 是给类型取别名
引用是给变量取别名
注意引用类型必须和引用实体是同种类型的
类型 引用变量名(对象名) 引用实体
int main()
{int a 0;//定义一个变量a,赋值为0,int b a;//这里的不是取地址符,而是引用,给变量取别名, 定义在一个类型和变量之间为引用//定义一个空间为a,又给这个空间a取别名为bint a 0;int b a;//这种写法和上面是完全不同的,//这里是 定义一个变量为a,a的值是0,定义一个变量为b,用a的0初始化return 0;
}如何证明是否公用一块空间? #include iostream
using namespace std;int main()
{int a 0;int b a;cout b endl;//取地址cout a endl;//取地址a;b;return 0;
} 6.2 引用的特性
1. 引用在定义时必须初始化
int main()
{int a 1;int b;//引用在定义时必须初始化return 0;
}
2. 一个变量可以有多个引用(可以取无限个别名)
int main()
{int a 1;int b a;int c a;int d c;//还可以给别名取别名a;return 0;
} 3. 引用一旦引用一个实体再不能引用其他实体
指针指向一个实体后,可以改变,引用不可以改变
int main()
{int a 1;int b a;int c a;int d c;int x 10;//引用一旦拥有一个实体,再不能引用其他实体b x;b是x的别名呢?还是x赋值为b?return 0;
} 这里把x赋值给b
6.3 常引用
权限不能放大
int main()
{int a 13;int b a;//权限不能放大const int c 20;//int d c;const int d c;//权限可以缩小,从只读的角度int e 25;const int f e; return 0;
}
隐式类型转换和强制类型转换都是会产生临时变量
所有的转换都不是对原变量进行转换和提升,而是之间产生临时变量
并不会改变原变量类型,
这里本质上是权限的放大和缩小
类型转换中间是会产生临时变量的,临时变量具有常性,相当于const修饰
int main()
{int ii 1;doubble dd ii;//int类型可以给double,会发生隐式类型转换double rdd ii;//double类型的数据可以变成int的引用吗?//不可以 这里不能引用的原因不是说类型不匹配,而是不能进行权限的放大const double rdd ii;//这里可以引用是因为权限的平移 中间产生的临时变量也是相当于const修饰的变量//此时rdd引用的不是ii,而是int转换成double之间产生的临时变量,//这个临时变量具有常性return 0;
} const 可以把一个常量起一个别名
const int x 10;
应用场景:
如果使用引用传参,函数内如果不改变n,那么尽量用const引用传参
const引用传参会有非常强的接受度 6.4 引用的使用场景 1.做参数 a.输出型参数 b.大对象传参,提高效率 2.做返回值 a.输出型返回对象,调用者可以修改返回对象. b.减少拷贝提高效率, 不是什么时候都可以使用传引用返回,要注意使用场景 出了作用域,返回对象还在可以用传引用返回 出了作用域,返回对象销毁.那么一定不能用引用返回,一定要用传值返回 1. 做参数 --(引用的输出型参数) 如果不用引用,传入的是实参的一份临时拷贝,形参的改变不会影响实参 如果想改变 必须使用指针 传入地址 在C里,这里x是a的别名,y是b的别名,x和y的交换就是a和b的交换 void Swap(int x, int y)
{int tmp x;x y;y tmp;
}
int main()
{int a 3;int b 5;cout 交换前: a b endl;Swap(a, b);cout 交换后: a b endl;return 0;
} 例如:有些书里会把数据结构里链表部分弄得很复杂
typedef struct SListNode
{.....
}SLTNode,*PSLTNode;
//这里的*PSLTNode 相当于typedef struct SListNode* PSLTNode 给这个结构体指针起了个别名 PSLTNode
void SListPushBack(PSLTNode phead,int x)//这里的引用相当于 phead是list的别名,phead的改变会影响list
{.....
}
int main()
{SLTNode* list NULL;SListPushBack(list,1);SListPushBack(list,1);SListPushBack(list,1);return 0;
}
大对象传参 提高效率
#include time.h
struct A{ int a[10000]; };
void TestFunc1(A a){}
void TestFunc2(A a){}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 clock();for (size_t i 0; i 10000; i)TestFunc1(a);size_t end1 clock();// 以引用作为函数参数size_t begin2 clock();for (size_t i 0; i 10000; i)TestFunc2(a);size_t end2 clock();// 分别计算两个函数运行结束后的时间cout TestFunc1(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl;
}
2. 做返回值
传值返回 都会生成一个返回对象拷贝作为函数调用的返回值 返回的是n吗 是用n的拷贝来做表达式的返回值 为什么编译器要这么做? 如果这里没有static ,n返回时,出了该作用域 会销毁 置为随机值 传引用返回:
引用返回的语法含义:返回返回对象的别名 不是什么时候都可以使用传引用返回,要注意使用场景 返回n的别名 越界了为什么不报错呢?
ret的结果是未定义的 如果栈帧结束时,系统清理栈帧置成随机值,那么这里ret的结果就是随机值
下面程序使用引用返回本质是不对的,结果是没有保障的 int Count()
{int n 0;n;// ...return n;
}
int main()
{int ret Count();return 0;
}
如果引用ret ,那么相当于 ret也是n的别名,结果会不会有所不同
int Count()
{int n 0;n;// ...return n;
}
int main()
{int ret Count();printf(%d\n, ret);printf(%d\n, ret);printf(%d\n, ret);printf(%d\n, ret);return 0;
} 总结:出了函数作用域,返回对象就销毁了,那么一定不能用引用返回,一定要用传值返回 什么时候可以用引用返回? 使用static
1. static修饰变量 a. 函数中局部变量 声明周期延长该变量不随函数结束而结束 初始化只在第一次调用该函数时进行初始化 记忆性后序调用时该变量使用前一次函数调用完成之后保存的值 存储位置不会存储在栈上放在数据段
int Count()
{static int n 0;n;// ...return n;
}
int main()
{int ret Count();printf(%d\n, ret);printf(%d\n, ret);printf(%d\n, ret);printf(%d\n, ret);return 0;
}
const引用
为什么这里给c取别名不可以? 本质上是权相的放大 c自己是const类型 不可以修改 用d取别名 使得d是权限的放大 可以修改 #include iostreamusing namespace std;int main()
{int a 10;//权限的的平移int b a;const int c 20;//权限的放大int d c;int e 30;//权限的缩小const intf e;//只读的角度变成你的别名return 0;
}
权限不可以放大,但是权限可以缩小 int main()
{int ii 1;double dd ii;//发生隐式类型转换double rdd ii;//double不可以变成int的引用//不可以使用的本质原因是 因为权限的放大,因为 int 类型要转换成double类型//中间要先生成一个double类型的临时变量,相当于 const double ii;//double dd const double ii; //权限的放大不可以const double rdd ii;//可以使用权限的平移return 0;
}
强制转换并不是改变原变量类型 他也是产生一个临时变量 如果使用引用传参,函数内如果不改变n,那么尽量用const引用传参
void func1(int n)
{}
void func2(const int n)
{}
int main()
{int a 10;const int b 20;func1(a);func1(b);func1(30);func2(a);func2(b);func2(30);double c 1.11;func2(c);return 0;
}
指针和引用的差别
指针和引用用途基本是相似的
但有
1.使用场景的差别
引用和指针的不同点:
1. 引用在定义时必须初始化指针没有要求
2. 引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型
实体
3. 没有NULL引用但有NULL指针
4. 在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占
4个字节)
5. 引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小
6. 有多级指针但是没有多级引用
7. 访问实体方式不同指针需要显式解引用引用编译器自己处理
8. 引用比指针使用起来相对更安全
2.语法特性以及底层原理的差别
从语法角度而言,引用没有开辟空间,指针开了四个字节或者8个字节的空间
底层实现角度,那么引用底层是用指针实现的 个人水平不足 如果代码中有错误可以多多在评论区指出一定会及时修改 谢谢大家看到这里 觉得有收获的话可以三连一下 一起加油