云南住房和城乡建设局网站,西安做官网的公司,策划网站做推广的公司,wordpress版权怎目录
1.引用的概念
2.引用的特征
3.常引用
4.引用使用场景
5.传值#xff0c;传引用效率比较
6.引用与指针的区别 1.引用的概念
引用不是新定义一个变量#xff0c;而是给已存在变量取了一个别名#xff0c;编译器不会为引用变量开辟内存空 间#xff0c;它和它引用…目录
1.引用的概念
2.引用的特征
3.常引用
4.引用使用场景
5.传值传引用效率比较
6.引用与指针的区别 1.引用的概念
引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间它和它引用的变量共用同一块内存空间。
语法 类型 引用变量名(对象名) 引用实体 示例
#includeiostream
using namespace std;int main()
{int a 0;int b a;//符号放在 类型和变量之间时是引用 其他是取地址一个符号多种用法cout a endl;cout b endl;//两个地址相同,a,b表示的是同一块空间a;cout b endl;//b也会1return 0;
} 注意引用类型必须和引用实体是同种类型的。
2.引用的特征
引用在定义时必须初始化 一个变量可以有多个引用引用一旦引用一个实体再不能引用其他实体
示例
int main()
{//int b;//1.引用在定义时必须初始化要不然不知道是谁的别名。int a 10;int b a;//2.一个变量可以有多个引用别名int c a;int d b;//也可以为引用取别名都是指的同一块空间//3.C一旦引用一个实体再不能引用其他实体int x 1;b x;//这里是赋值不是把b改成x的别名return 0;
}3.常引用
注意在引用过程中权限可以平移可以缩小但是不能放大。
什么意思呢我们看下面代码const是常量限定符被const修饰的值不能被修改
int main()
{const int a 0;//a不能被修改//int b a;//1.权限放大报错因为b没有用const修饰可以被修改int b a;//简单赋值操作可以const int c a;//2.权限的平移//3.权限的缩小int x 0;const int y x;//x可以修改修改后y也会改变但不能直接修改yreturn 0;
}
临时变量
程序在运行时会产生临时变量只在调用期间有效这些临时变量具有常属性它们的值不能被修改以下三种情况会产生临时变量
值传递函数传值传指针以及函数值返回引用时实参和形参的类型不匹配强制类型转换 引用时实参和形参的类型不匹配 如果取别名时引用类型与引用实体类型不同会发生截断类型提升转换时中间都会产生临时变量然后这个引用就是临时变量的别名因为这个临时变量具有常属性不能修改所以引用时也需要用const修饰引用的是中间产生的临时变量。如果没有被const修饰那这个引用的值可以被修改权限放大会报错。 int main()
{int i 0;//double d i;//赋值可以//int d i;//可以权限平移//double d i;错误类型不同产生临时变量d没有被const修饰可以被修改权限放大const double d i;//正确写法return 0;
}
值传递函数值返回
int func()
{int a 0;return a;
}int main()
{int ret func();//传值返回函数返回过程中会用临时变量保存返回的值拷贝可以//int ret1 func(); //传值返回 中间生成的临时变量具有常性不能修改这里权限放大const int ret1 func();//权限平移可以return 0;
}
4.引用使用场景
1.做参数
#includeiostream
using namespace std;void Swap(int x, int y)
{int t x;x y;y t;
}int main()
{int a 1;int b 2;Swap(a, b);cout a a b b endl;return 0;
}2.做返回值 如果函数返回时出了函数作用域如果返回对象还在还没有还给系统没有被销毁如全局变量堆区开辟的空间以及静态变量则可以使用引用返回如果已经还给了系统则必须使用传值返回 不能返回局部变量的引用引用的这块空间可能被修改。示例
//传引用返回相当于返回的是n的引用
int Count()
{int n 0;n;return n;
}int main()
{int ret Count();//这里打印的值可能是1也可能是随机值cout ret endl;//X86下第一次不受影响是因为调用cout函数先传参,取值之前还没有被覆盖。//然后ret位置的值才会被覆盖覆盖之后ret的这块空间可能已经被修改cout ret endl;return 0;
}
下面代码输出什么结果为什么
int Add(int a, int b)
{int c a b;return c;
}
int main()
{int ret Add(1, 2);Add(3, 4);cout Add(1, 2) is : ret endl;//7return 0;
} 5.传值传引用效率比较
以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直 接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效 率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低。
代码
#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;
} 可以发现传值效率非常低引用它需要拷贝大量的数据传引用效率就非常高了。
6.引用与指针的区别
在语法概念上引用就是一个别名没有独立空间和其引用实体共用同一块空间。
int main()
{int a 10;int ra a;couta aendl;coutra raendl;//两个地址相同return 0;
}
在底层实现上实际是有空间的因为引用是按照指针方式来实现的。
我们来看下面代码以及这段代码的汇编代码 可以发现指针和引用底层汇编代码是相同的但是它们两个的语法不同。 引用和指针的不同点: 引用概念上定义一个变量的别名指针存储一个变量地址。引用在定义时必须初始化指针没有要求引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型实体没有NULL引用但有NULL指针在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个字节)引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小有多级指针但是没有多级引用访问实体方式不同指针需要显式解引用(使用*解引用)引用由编译器自己处理引用比指针使用起来相对更安全 本篇结束。