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

北京市网上服务平台登录在线优化工具

北京市网上服务平台登录,在线优化工具,软件开发教程自学教程,辽宁建设工程网【C初探#xff1a;简单易懂的入门指南】二 1.引用1.1引用做函数的参数1.2 引用做返回值1.2.1 关于引用做返回值的几点补充 1.3 多引用(对一个变量取多个别名)1.4 引用类型一致性原则以及权限的问题阐述1.5引用的效率问题1.6引用和指针的比较 2.auto关键字2.1 auto关键字的使用… 【C初探简单易懂的入门指南】二 1.引用1.1引用做函数的参数1.2 引用做返回值1.2.1 关于引用做返回值的几点补充 1.3 多引用(对一个变量取多个别名)1.4 引用类型一致性原则以及权限的问题阐述1.5引用的效率问题1.6引用和指针的比较 2.auto关键字2.1 auto关键字的使用细则2.2 auto关键字不能使用的场景 3.特殊的for循环(基于范围)3.1基于范围for的语法3.2 基于范围for的使用规则 ❤️博客主页 小镇敲码人 欢迎关注点赞 留言 收藏 任尔江湖满血骨我自踏雪寻梅香。 万千浮云遮碧月独傲天下百坚强。 男儿应有龙腾志盖世一意转洪荒。 莫使此生无痕度终归人间一捧黄。 ❤️ 什么你问我答案少年你看下一个十年又来了 1.引用 引用是C与C不同的点之一它虽然是给变量取别名算不上一个新定义的概念但是它和typedef的区别还是存在的例如它可以在函数做参数和返回值时使用但是typedef没有这种功能是一个操作符表示引用你可以理解为要给一个变量取别名。 1.1引用做函数的参数 下面我们给出一段代码帮助你理解引用的最常见的功能 #includeiostream using namespace std;int Add(int a, int b) {return a b; }int main() {int a 3;int b 4;int c Add(a, b);cout ab c endl;return 0; }运行结果截图 上面Add函数的两个参数就是实参a和b的别名就相当于我们人类社会里的绰号就比如你叫张三你的同学可能叫你老张你的家里人可能叫你三儿虽然叫法不同但是它们都代表你这个人而且引用是不额外开空间的我们可以利用下面的代码简单的验证一下 #includeiostream using namespace std;void Fun(int b) {cout b的地址为 b endl; }int main() {int a 3;Fun(a);cout a的地址为 a endl;return 0; }运行截图为 可以看到这里引用是不开空间的因为b是a的别名所以编译器不会给它们开两份空间。 1.2 引用做返回值 #includeiostream using namespace std;int Add(int a, int b) {static int c a b;cout c的值为 c endl;cout c的地址为 c endl;return c; }int main() {int a 3;int b 4;int d Add(a, b);cout d的值为 d endl;cout d的地址为 d endl;return 0; } 运行结果 这里d就是c的别名所以它们的地址是一样的static修饰c,是因为临时变量开在栈区出了函数的作用域它就销毁了但是如果加了staticc就变成了静态变量静态变量的空间是开在静态区的程序的结束它的生命周期才算结束至于为什么d作为c的别名在外面还可以访问可以类比函数以引用传参理解这里博主认为引用扩大了c的的作用域只要c的生命周期没结束它以引用返回在main函数里面我们就是能访问到c。 如果你不相信我们可以通过如下代码简单的验证一下 #includeiostream using namespace std;int Add(int a, int b) {static int c a b;cout c的值为 c endl;cout c的地址为 c endl;return c; }int main() {int a 3;int b 4;int d Add(a, b);d;Add(a, b);return 0; }运行结果截图 这里注意一点由于c开在静态区只要程序不结束它的空间一直不会被系统回收所以定义c那部分代码是不会重新执行一次的这恰好可以帮助我们验证以引用返回就可以在main函数里面访问原本作用域在Add函数里面的静态变量c。 1.2.1 关于引用做返回值的几点补充 细心的朋友可能会在vs2019上发现这样的问题上述代码即使不加static似乎也能正常运行。 这里博主认为是编译器检查机制的一个漏洞系统没有将空间及时的回收如果我把代码改成这样系统把空间回收使用后d的值就变成随机值了 但是如果你加了static就不会出现这种问题 1.3 多引用(对一个变量取多个别名) 在C中我们是支持对一个变量进行多次引用的 #includeiostream using namespace std;int main() {int a 3;int b a;int c a;int d a;cout b的地址为 b endl b的值为 b endl;cout c的地址为 c endl c的值为 c endl;cout d的地址为 d endl d的值为 d endl;c 2;cout b的地址为 b endl b的值为 b endl;cout c的地址为 c endl c的值为 c endl;cout d的地址为 d endl d的值为 d endl;return 0; }运行结果截图 而且由于引用只是取别名本质上它们是同一个变量所以修改一个就修改了它们所有的值。 1.4 引用类型一致性原则以及权限的问题阐述 上述代码如果加上这样一行就会报错 #includeiostream using namespace std;int main() {int a 3;int b a;double c a;int d a;cout b的地址为 b endl b的值为 b endl;cout c的地址为 c endl c的值为 c endl;cout d的地址为 d endl d的值为 d endl;c 2;cout b的地址为 b endl b的值为 b endl;cout c的地址为 c endl c的值为 c endl;cout d的地址为 d endl d的值为 d endl;return 0; }报错截图 所以我们在定义引用时不能改变原变量的类型。 关于权限的问题主要围绕const这个关键词展开 const修饰的变量当对其引用时不能不加const,因为其是不可修改的常量不加const是对其权限的放大编译器是不允许的。但是如果一个变量没有被const修饰在引用时可以加上const,进行权限的缩小这个编译器是允许的。 但是缩小权限又是允许的 这里有个比较奇怪的现象为什么我const修饰b这个别名b不能修改我却可以通过修改a来修改a的值,与此同时b的值也被修改了这里本博主也比较疑惑大家可以在评论区或者私信来教教博主。关于引用还有一点需要说明引用必须给初始值引用的对象可以是全局变量、临时变量、但不能是常量const修饰的变量例外。 1.5引用的效率问题 引用的效率是很高的因为它不会额外的去开空间下面两段代码希望可以帮助你来理解 传值和引用传参的效率比较 #includeiostream using namespace std; #include time.hstruct A {int a[100000]; }; void TestFunc1(A a) {} void TestFunc2(A a) {} void TestRefAndValue() {A a;// 以值作为函数参数size_t begin1 clock();for (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; }运行截图 这里clock函数是表示当前程序运行的时间单位是毫秒可以看到传值和传引用的效率差的还是很大。 传值返回和传引用返回的效率比较 includeiostream using namespace std; #include time.hstruct A {int a[100000]; }; A 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(A)-time: end1 - begin1 endl;cout TestFunc2(A)-time: end2 - begin2 endl; }int main() {TestRefAndValue();return 0; }运行截图 可以看到由于传值传参和传值返回都需要额外拷贝开一份空间而传引用不需要所以效率是差别还是很大的所以一般情况下如果不是特殊需求传引用的性价比还是更高的。 1.6引用和指针的比较 相同点 效率都很高。底层汇编代码很相似引用的底层实现是指针也就是引用在底层实现上是开了空间的。传址引用和传引用返回都可以改变该变量的值当然特殊情况例外(const修饰的变量)。 不同点 1.引用在语法概念上没有开空间。 2.指针不初始化不会报错但是引用不行。 3.创建一个引用之后这个引用就不能再作为其它变量的别名了但是指针变量可以指向其它相同类型的变量。 2.auto关键字 auto是C上面的一个关键字它可以自动识别右值的类型我们主要介绍C11标准的auto关键字。 #includeiostream using namespace std;int Add(int a, int b) {static int c a b;return c; } int main() {int a 2;int b 3;auto c Add(a, b);cout b的类型为 typeid(b).name() endl;return 0; }运行结果 注意引用的类型和被引用的对象是一致的typeid(变量名).name()可以用来打印变量的类型。 可能会有人认为这样没有什么实质的作用但是当那个函数的返回值类型因为C有很多自定义类型非常复杂时auto关键字就非常方便了。 2.1 auto关键字的使用细则 auto关键字可以和指针、引用结合起来使用但是必须给它初始化否则语法上是无法通过的。 #includeiostream using namespace std; int main() {int a 2;int b 3;auto* c a;auto d a;auto e a;cout c的类型为 typeid(c).name() endl;cout d的类型为 typeid(d).name() endl;cout e的类型为 typeid(e).name() endl;return 0; } 运行截图 这里在定义指针时auto和auto*没有什么区别但是在定义引用时必须加上操作符。 如果不初始化就会报这样的错误 这也间接说明了auto不是一个存储类型指示符而是作为一个新的类型指示符来指示编译器auto声明的变量的类型必须由编译器在编译时期推导而得所以如果你不给初始值那么编译器就无法进行推导,auto在编译期间会被替换。 auto关键词可以同时定义很多变量但是它只会对第一个变量的类型进行推导从而用这个变量的类型来定义其它变量所以这些变量的类型要相同详细请看下图 2.2 auto关键字不能使用的场景 auto关键字不能作为函数的参数因为编译器无法对其类型进行推导。auto不能用来声明数组。 这里有一点需要说明的时虽然VS2019上以auto作为返回值的类型是可以编译通过的但还是不建议这样去做因为如果我们后期想要去找到其返回值的类型还是比较麻烦的因为可能出现这样的情况 这里还只有两个嵌套如果工程量一大嵌套的次数变多想知道某个函数的返回值就是一件困难的事情有人说可以用typeid(变量名).name()来知道其类型我直接写出来不是更方便吗 auto在实际中最常见的优势用法就是跟以后会提到的C11提供的新式for循环还有lambda表达式等进行配合使用。 3.特殊的for循环(基于范围) 3.1基于范围for的语法 在C语言/C98中如果我们想遍历一个数组你可能会这样做 #includeiostream using namespace std;int main() {int array[] { 1,2,3,4,5,6,7,8 };for (int i 0; i sizeof(array) / sizeof(array[0]); i){array[i] * 2;}for (int* p array; p array sizeof(array) / sizeof(array[0]); p){cout *p ;}return 0; }但是对于一个本身就有范围的集合来说我们程序员自己去控制范围似乎有点多余了而且还很容易出错因此C11中引出了基于范围的for循环。它的for循环括号里被:分为两部分左边是用来迭代的变量(迭代可以理解为遍历)右边是范围代码是这样实现的 #includeiostream using namespace std;int main() {int array[] { 1,2,3,4,5,6,7,8 };for (auto p : array){p * 2;}for (auto p : array){cout p ;}return 0; }这里auto可以换成数组相应的类型但是使用auto编译器可以帮助我们在编译期间推导类型十分方便但是我们如果想要改变数组的值就得使用引用了因为如果不是引用左边的变量只是我们数组值的一个拷贝改变它不能改变我们数组中的值。 下面一段代码希望帮助你完全理解它们 #includeiostream using namespace std;int main() {int array[] { 1,2,3,4,5,6,7,8 };for (int i 0; i sizeof(array) / sizeof(array[0]); i){cout array[i] ;}cout endl;for (auto p : array){cout p ;}cout endl;for (auto p : array){cout p ;}return 0; }运行结果 我们可以看到引用是控制台第三行它的地址与数组每个元素的地址是相同的说明编译器在迭代时如果是引用每执行一次for循环p的空间就会被回收不然由于创建引用变量后这个引用变量不能作为其它变量的别名可知打印出的地址应该是相同的才对此时不相同所以博主猜测应该是回收了一次for循环执行一次引用变量的创建至于普通的迭代可以看出第二行的地址是完全相同的说明编译器只给这个变量开了一次空间剩下的每次for循环都是简单的把数组中的值赋值给它。 3.2 基于范围for的使用规则 for循环的范围必须是确定的。 对于数组而言它的范围就是从第一个元素到最后一个元素 注意以下代码就有问题它的范围是不确定的。 #includeiostream using namespace std;void Fun(int array[]) {for (auto p : array){cout p ;} } int main() {int array[] { 0,1,2,4,3,5 };Fun(array);return 0; }报错截图 这是你这样写array似乎是一个数组其实不然它是一个保存了数组首元素的指针你在里面计算数组的范围是无法计算出来的 所以你也无法知道范围自然就会报错。
http://wiki.neutronadmin.com/news/24868/

相关文章:

  • 做爰全过程免费的视频凤凰网站在线微信小程序
  • 网站名称要求吸引企业做网站的文章内容
  • 做贺卡 网站做网站的客户在哪找
  • 做app还是做网站合适6静态网站设计怎么做
  • 宁夏住房和城乡建设厅门户网站附近图文广告公司电话
  • 做网站的常识网站建设制作教程
  • 商城网站需要注意事项赣州门户网站建设
  • 网站设计是干什么的网站备案的账号找不到
  • 中砼建设有限公司网站建设银行如何招聘网站
  • 创建网站怎么弄制作介绍的网站模板
  • 网站标头图片切换民治网站建设公司
  • 网站推广的软文深圳建设交易宝安
  • 江西那家做网站公司好小程序开发平台要多少钱
  • 免费 网站模板网站如何添加统计代码
  • 铜仁市网站建设服装加工平台
  • 个人怎么做一个网站集团做网站
  • 2018做网站 工具程序源码网站
  • asp免费网站模板wordpress提交工单
  • 鲜花网站建设规划书软件制作app
  • 文章网站是怎么做的建筑工程承包网沈阳
  • 张家口购物网站开发设计asp.net做网站的流程
  • 直播网站开发核心技术wordpress支持php几
  • 网站建设基本技术网站开发组合 lamp
  • 长尾关键词查询珠海优化seo
  • 低价网站建设费用预算容桂做外贸网站
  • 西安道桥建设有限公司网站四川城乡和住房建设厅网站
  • 企业公司网站建设公司wordpress上传主题没有反应
  • 多元网站宁波seo排名优化培训
  • 佛山哪里有网站开发?网站建设百度认证
  • 极致优化WordPress网站速度网站制作和设计需要多少钱