当前位置: 首页 > news >正文

一级a做片性视频 网站在线观看网站建设有多少公司

一级a做片性视频 网站在线观看,网站建设有多少公司,做点心的网站,河南省教育厅官方网站师德建设目录 一. 前言 二. 引用 2.1 引用的概念 2.2 引用的使用 2.3 引用的特性 2.4 常引用 2.5 引用的使用场景 2.6 传值、传引用效率比较 2.7 引用和指针的区别 三. 内联函数 3.1 内联函数的概念 3.2 内联函数的特性 一. 前言 上期说道,C是在C的基础之上&…


目录

一. 前言

二. 引用

2.1 引用的概念

2.2 引用的使用

2.3 引用的特性

2.4 常引用

2.5 引用的使用场景

2.6 传值、传引用效率比较

2.7 引用和指针的区别

 三. 内联函数

3.1 内联函数的概念

3.2 内联函数的特性 


一. 前言

        上期说道,C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。我们介绍了部分C++为了补充C语言语法上的不足而新增的内容,如命名空间,缺省参数,函数重载等等,上期传送门【C++深入浅出】初识C++(上篇)http://t.csdn.cn/UjbIo        本期将继续介绍C++剩下的一些有趣的功能,如引用内联函数等等,这也是为了后面的类和对象打好基础。 

          话不多说,直接上菜!!!

二. 引用

2.1 引用的概念

        引用并不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

        引用就相当于我们给别人起昵称。例如你叫你女朋友小笨猪,那么对你而言,小笨猪就是你的女朋友,和叫名字是一个意思,既不是其他任何人,你也不会因此多一个女朋友

2.2 引用的使用

        类型& 引用变量名(对象名) = 引用实体

void Test()
{int a = 10;int& ra = a; //<====定义引用类型,此时ra就是变量a的别名,ra与a是同一块内存空间printf("a的地址为%p\n", &a);printf("ra的地址为%p\n", &ra);
}int main()
{Test();return 0;
}

我们看到变量a和引用变量ra的地址是一样的,说明它们共用同一块内存空间。

 2.3 引用的特性

        使用引用时需要注意以下几点特性

         1、引用在定义时必须初始化

int main()
{int a = 10;int& b; //错误写法,会报错int& b=a; //正确写法return 0;
}

         2、一个变量可以有多个引用

int main()
{int a = 10;//下面的b,c,d均是变量a的别名int& b = a;int& c = a;int& d = c;printf("%p %p %p %p\n", &a,&b,&c,&d);return 0;
}

          3、引用一旦引用一个实体,就不能引用其他实体

int main()
{int a = 10;int& b = a; //b是a的别名int c = 20; //能不能将b改成c的别名呢?b = c; //不行,这条语句是将c的值赋给引用变量b,即修改变量a的值,并不是让b引用cprintf("&a = %p &b = %p &c = %p\n", &a,&b,&c);printf("a = %d b = %d c = %d\n", a, b, c);return 0;
}

          4、引用类型必须和引用实体是同种类型的

int main()
{int a = 10;double& b = a; //这种写法会报错return 0;
}

        我们看到编译器报错说非常量限定,那如果我们加上const修饰呢?如下:

    const double& b = a;

        我们惊讶地发现通过了编译,说明上面不是因为int和double类型不一样而报错,那究竟是为什么呢?下面我们来分析分析

         实际上,由于引用实体和引用变量的类型不同,编译器会自动进行隐式类型转换。编译器会生成一个double类型的临时变量tmp,然后将a的内容以某种形式放到临时变量tmp中,最后再让b引用临时变量tmp

int main()
{int a = 10;const double& b = a;//类似于下面的步骤int a = 10;double tmp = a; //将a的值转换赋给tmpconst double& b = tmp; //b再引用tmpreturn 0;
}

         由于临时变量具有常属性,因此tmp的类型就是const double,用double类型的引用变量引用const double类型的变量,这无疑是一种权限的放大,是不被允许的。就好比别人大门紧缩不然你进,你偏偏另辟蹊径从窗户翻入,这无疑是犯法的,私闯民宅。这就是为什么编译器会报出非常量限定的错误的原因,引用变量d需要加上const修饰,权限的平移是被允许的。

        最后,本来临时变量tmp在当前语句结束后就会被销毁,但此时被b所引用,其生命周期就自动被延长了

         分析了这么多,下面我们用代码来进行验证一下:

int main()
{int a = 10;const double& b = a;printf("&a = %p , &b = %p\n", &a, &b); //求a,b空间的地址printf("修改前 a = %d , b = %.2lf\n", a, b);a = 20;//b = 30; //这句代码会报错,被const修饰的变量不可修改printf("修改后 a = %d , b = %.2lf\n", a, b);return 0;
}

我们发现a的地址和b的地址不同,这说明了b并不是变量a的引用,而是引用了新形成的临时变量。并且,当我们对a进行修改时,b中的内容并没有发生改变,这也印证了a和b不是同一块内存空间。最后,当我们想要对b的内容进行修改时,编译器会直接报错,说明b所在的空间具有常属性


2.4 常引用

        被const关键字修饰的引用变量我们称为常引用。我们无法通过常引用来修改引用实体的值,如下:

#include<iostream>
using namespace std;
int main()
{int a = 10;const int& b = a;//b++; //会报错,b是常引用,无法修改a++; //a是普通变量,允许修改cout << "a = " << a <<' ' << "b = " << b;return 0;
}

        前面我们提到了权限不能放大,也就是说:普通引用不能引用常属性变量。但是,权限允许平移或者缩小,即常引用可以引用常属性变量常引用可以引用普通变量。如下:

#include<iostream>
using namespace std;
int main()
{int a = 10;const int& b = a; //权限的缩小,const引用引用普通变量,编译正常const int aa = 10;const int& bb = aa;//权限的缩小,const引用引用const变量,编译正常int& cc = aa;//权限的放大,普通引用引用const变量,报错return 0;
}

 2.5 引用的使用场景

        引用的使用场景一般有两个:做函数参数做函数返回值

        1、引用作为函数参数

        C语言中,如果我们调用函数时使用传值调用,那么形参的改变是不会影响实参的,形参是实参的临时拷贝。如果我们想在函数中对实参进行修改,那就必须使用传址调用,通过地址对实参的值进行修改。

        而在C++中,新增了引用的语法,我们可以使用引用作为函数的形参,此时形参就是实参的一个别名,并不会额外开辟空间,形参和实参共同内存空间,修改形参也就是对实参进行修改。具体实现方式如下

#include<iostream>
using namespace std;
void ModifyFun(int& x) //引用作为函数参数
{x = 100;
}
int main()
{int a = 10;cout << "调用前" << a << endl;ModifyFun(a);cout << "调用后" << a << endl;
}


#include<iostream>
using namespace std;
void Swap(int& x , int& y) //引用作为函数参数
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 10;int b = 20;cout << "交换前:" << "a = " << a << " b = " << b << endl;Swap(a, b);cout << "交换后:" << "a = " << a << " b = " << b << endl;
}

        2、引用作为函数返回值

        引用也可以作为函数的返回值,如下:

#include<iostream>
using namespace std;
int& Count()
{static int n = 0; //n是一个静态变量,函数调用结束后不会销毁cout << n << endl;;return n;
}
int main()
{int& k = Count();k++;Count();return 0;
}

在Count()函数通过引用返回n,此时main函数中的引用变量k就是n的别名,当我们在main函数中修改k,就相当于对静态变量n做修改。

        但是,如果以下情况使用引用返回会出现什么情况呢? 

int& Add(int a, int b)
{int c = a + b; //c是局部变量,Add调用结束后被销毁return c;
}
int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :" << ret << endl;return 0;
}

 很惊讶的发现,最终ret变量的值不是3而是7,为什么呢?

 这就要来谈谈上述代码出现的野引用问题了。

我们通过下图来进行分析 

 总结:函数返回时,如果出了函数作用域,返回对象还在(还没销毁还给系统),则可以使用
引用返回;如果已经还给系统了,则必须使用传值返回。

2.6 传值、传引用效率比较

        在C/C++中,以值作为参数或者返回值类型,在传参和返回期间,函数并不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,因此用值作为参数或者返回值类型,需要额外进行拷贝,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

        而如果以引用作为参数或者返回值类型,由于引用是作为变量的别名,并不会额外开辟空间形成拷贝。因此在传参和返回期间,就相当于直接传递实参或将变量本身直接返回,效率大大提升。下面我们通过代码来更直观地看看二者的效率差距:

        值和引用作为函数参数的效率差距

#include <time.h>
struct A { int a[10000]; };
void TestFunc1(A a)
{;
}
void TestFunc2(A& a)
{;
}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock(); //clock()函数返回程序运行到调用clock()函数所耗费的时间,单位是msfor (size_t i = 0; i < 100000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{TestRefAndValue();return 0;
}


         值和引用作为返回值类型的效率差距

#include <time.h>
struct A 
{int a[10000]; 
}a;
// 值返回
A TestFunc1() 
{ return a; 
}
// 引用返回
A& TestFunc2() 
{ return a; 
}
void TestRefAndValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{TestRefAndValue();return 0;
}

通过上述代码的比较,我们发现传值和引用在作为传参以及返回值类型上效率相差很大。传引用的效率远高于传值。因此能使用引用就尽量使用引用,提高效率。

2.7 引用和指针的区别

        在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

        但在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。这点我们可以参照二者编译后生成的汇编代码证明

int main()
{//引用int a = 10;int& ra = a;//指针ra = 20;int* pa = &a;*pa = 20;return 0;
}

可见,引用和指针的汇编代码是一模一样的,最后都是通过变量a的地址来修改a。


不过,引用和指针还是有不同点的,如下:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 引用必须初始化,故没有NULL引用,但有NULL指针
  5. sizeof的含义不同,sizeof(引用变量)的结果为引用实体的类型大小,而sizeof(指针)始终是地址空间所占字节个数(32位平台下占4个字节,64位平台下占8个字节)
  6. 引用自增即引用的实体增加1,指针自增即指针向后偏移一个类型的大小
  7. 多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 安全性的角度,引用比指针使用起来相对更安全

三. 内联函数

3.1 内联函数的概念

        以inline关键字修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,不会调用函数建立栈帧,因此内联函数提升程序运行的效率。
        我们可以通过汇编代码来验证加上inline的函数是否会被调用

        没加inline关键字:

int Add(int x, int y)
{return x + y;
}
int main()
{int ans = 0;ans = Add(1, 2);return 0;
}

          加上inline关键字:

inline int Add(int x, int y)
{return x + y;
}
int main()
{int ans = 0;ans = Add(1, 2);return 0;
}

可以看到,内联函数并不会生成对应的call指令,而是直接被替换到函数调用处,减少了调用函数建立栈帧的开销。

          注意事项:

          内联函数的效果需要在release模式才会体现。因为在debug模式下编译器默认不会对代码进行优化,顾不会进行展开。当然我们也可以进行设置,方法如下(VS2022):

1、找到当前项目属性设置页:

 2、设置调试信息格式:

  3、设置内联函数扩展:


3.2 内联函数的特性 

主要有如下几点特性:

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用。缺陷:可能会使目标文件变大;优势:少了调用建立栈帧开销,提高程序运行效率。
  2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
    议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性(编译器也是很聪明的,可不要贪杯噢)。以下为《C++prime》第五版关于inline的描述:
  3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,符号表中就没有函数地址了,链接就会找不到。
    // in.h
    #include <iostream>
    using namespace std;
    inline void f(int i);// in.cpp
    #include "in.h"
    void fun(int i)
    {cout << i << endl;
    }// main.cpp
    #include "in.h"
    int main()
    {fun(10);return 0;
    }

    报错原因:由于in.h文件中只有函数的声明没有定义,顾在编译阶段main.cpp中的fun() 函数无法进行展开,只能在链接阶段进行链接。但是由于in.cpp的fun()函数被声明为内联函数,fun()函数并不会进入符号表,最后就会导致链接时找不到函数地址,报错。


以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏

http://www.hkea.cn/news/867240/

相关文章:

  • 网站建设洪塔网站搜索优化排名
  • 专业做设计师品牌网站深圳百度总部
  • 网站兼容工具seo关键词排名优化教程
  • O2O网站制作需要多少钱美区下载的app怎么更新
  • 上海做网站 公司做电商必备的几个软件
  • caozi.com网站建设中百度指数如何分析数据
  • 互联网舆情处置公司武汉seo外包平台
  • 消防器材网站建设背景seo工作职位
  • 专业网站制作公司名称seo咨询茂名
  • 做b2c网站建网站seo
  • 代理注册香港公司seo技术交流论坛
  • 想要提高网站排名应该怎么做seo网站推广费用
  • 专业做食材网站seo链接优化建议
  • 做画册的网站附近哪里有计算机培训班
  • 大兴建站推广google登录
  • 长春个人做网站哪家好百度指数热度榜
  • 嘉兴手机网站开发费用百度学术论文官网入口
  • 刷业务网站怎么做seo关键词挖掘
  • 企业移动网站品牌苏州网站外包
  • 网站建设流程 文档东莞seo技术
  • 公众号开发网站建设合同信息流广告投放流程
  • 长清网站建设费用友情链接出售平台
  • 先做网站再付款百度推广的广告真实可信吗
  • 湖南省人民政府一事一办企业网站seo排名优化
  • 深圳招聘网官方网站网站搜索引擎优化
  • 怎么知道一个网站是谁做的中国最大的企业培训公司
  • m2c是什么意思南昌百度seo
  • 专业做羽绒服的服装网站域名注册网
  • 公司网站建设需要显示什么软件世界球队最新排名
  • 做微信平台图片网站有没有免费的广告平台