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

网站空间空间租赁天津网站建设代理商

网站空间空间租赁,天津网站建设代理商,建站行业发展,无锡本地模板网站建设目录 1.内联函数 1.1 概念 1.2 特性 1.3 内联函数与宏的区别 2.auto关键字(C11) 2.1 auto简介 2.2 auto的使用细则 2.3 auto不能推导的场景 3.基于范围的for循环(C11) 3.1 范围for的语法 3.2 范围for的使用方法 4.指针空值nullptr(C11) 4.1 C98中的指针空值 1.内联…

目录

1.内联函数

1.1 概念

1.2 特性

 1.3 内联函数与宏的区别

2.auto关键字(C++11)

2.1 auto简介

2.2 auto的使用细则

2.3 auto不能推导的场景

3.基于范围的for循环(C++11)

3.1 范围for的语法

3.2 范围for的使用方法

4.指针空值nullptr(C++11)

4.1 C++98中的指针空值


1.内联函数

1.1 概念

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。

inline int Add(int left, int right)
{return left + right;
}int main()
{int ret = 0;ret = Add(1, 2);return 0;
}

如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的
调用

查看方式:

  1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add,而release模式下不能调试,所以采用第二种方法。
  2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2022的设置方式)

右键点击解决方案管理器中的项目名称,打开属性,设置下面两个选项。 

 发现没有使用调用函数指令call,没有调用Add函数,而是直接在这里展开了内联函数。

1.2 特性

  • inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
  • inline对于编译器而言只是一个建议当不当做内联函数还需要编译器自己判断,不同编译器对于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为《C++prime》第五版关于inline的建议:
  • inline不建议声明和定义分离,分离会导致链接错误。因为内联函数在编译时展开,如果只有声明,就找不到,只能通过函数调用,但是符号表中没有内联函数,因为内敛函数不生成指令,不会进入符号表。
  • 内联函数推荐在头文件中定义。当然内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,如果其他源文件使用必须拷贝一份定义。当然定义在头文件中,包含头文件时编译器会帮你拷贝一份,不用自己拷贝。
  • 关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。(声明前可以不用加 inline)

 1.3 内联函数与宏的区别

  1. 内联函数是在编译时展开(编译器),而宏在预编译时展开(预处理);在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
  2. 内联函数可以进行类型安全检查、自动类型转换、语句是否正确等编译功能,宏不具有这样的功能。
  3.  宏在定义时要注意宏参数,一般用括号括起来,否则容易出现二义性。而内联函数不会出现二义性。
  4. .宏定义不是真正的函数,没有参数类型检查,不安全;而内联函数是真正的函数,有类型检查,更为安全。

宏函数实现Add。

#include<iostream>
using namespace std;
#define ADD(x,y) ((x)+(y))
int main()
{int a = ADD(1, 2);//printf("%d\n", ADD(1, 2));宏不能带分号// #define ADD(x,y) x+y//printf("%d\n", ADD(1, 2)*3);//不加括号变为1+2*3cout << a << endl;//#define ADD(x,y) (x+y)int b = 1, c = 2;ADD(b | c, b & c);//x和y不加括号(x+y) 会变为b|c+b&c,+优先级比位操作符高return 0;
}

【面试题】

宏的优缺点?
优点:

  1. 增强代码的复用性,没有类型的严格限制。
  2. 提高性能,针对频繁调用的小函数,不需要再建立栈帧。

缺点:

  1. 不方便调试宏。(因为预编译阶段进行了替换)
  2. 导致代码可读性差,可维护性差,容易误用。
  3. 没有类型安全的检查。

C++有哪些技术替代宏?

1. 常量定义 换用const enum
2. 短小函数定义 换用内联函数

2.auto关键字(C++11)

2.1 auto简介

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量

在C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得

int TestAuto()
{return 10;
}int main()
{int a = 10;//int b = a;//auto 赋值时,可以通过右边的值自动推导左边值的类型auto b = a;auto c = 'a';auto d = TestAuto();cout << typeid(b).name() << endl;//可以得到变量的类型cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化return 0;
}

【注意】

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。


有什么用处呢? 随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:

  1. 类型难于拼写
  2. 含义不明确导致容易出错

比如我们C++以后要学习的std::map<std::string, std::string>::iterator 是一个类型,但是该类型太长了,特别容易写错。这时可以使用auto自动推导类型。

int main()
{//普通情况下,没有价值//类型名很长,就会有价值std::vector<std::string> v;//std::vector<std::string>::iterator it = v.begin();auto it = v.begin();return 0;
}

2.2 auto的使用细则

1. auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

int main()
{int x = 10;auto a = &x;auto* b = &x;//与上一行相同auto& c = x;cout << typeid(a).name() << endl;cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;*a = 20;*b = 30;c = 40;return 0;
}

2. 在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

void TestAuto()
{auto a = 1, b = 2;auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

2.3 auto不能推导的场景

1. auto不能作为函数的参数

// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}

2. auto不能直接用来声明数组

void TestAuto()
{int a[] = {1,2,3};auto b[] = {4,5,6};//编译失败
}

3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法

4. auto在实际中最常见的优势用法就是跟下面会讲到的C++11提供的新式for循环,还有后面会学的lambda表达式等进行配合使用
 

3.基于范围的for循环(C++11)

3.1 范围for的语法

在C++98中如果要遍历一个数组,可以按照以下方式进行

void TestFor()
{int array[] = { 1, 2, 3, 4, 5 };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 << endl;
}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因
此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范
围内用于迭代的变量,第二部分则表示被迭代的范围。

void TestFor()
{int array[] = { 1, 2, 3, 4, 5 };for(auto& e : array)//会依次取array中的元素赋值给ee *= 2;//for(auto* e : array)//这种写法不对,因为array中的元素类型是int类型//    (*e) *= 2;      //不是一种地址,这里会发生类型不匹配for(auto e : array)cout << e << " ";
}

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

3.2 范围for的使用方法

1. for循环迭代的范围必须是确定的

对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

注意:以下代码就有问题,因为for的范围不确定,因为函数传参,array这里只是地址,不是代表一个数组。

void TestFor(int array[])
{for(auto& e : array)cout<< e <<endl;
}

2. 迭代的对象要实现++和==的操作。(关于迭代器这个问题,以后会讲,现在提一下,没办法
讲清楚,现在大家了解一下就可以了)
 

4.指针空值nullptr(C++11)

4.1 C++98中的指针空值

在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现
不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下
方式对其进行初始化:

void TestPtr()
{int* p1 = NULL;int* p2 = 0;// ……
}

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

条件编译指令,可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如在函数重载中:

void func(int)//参数类型匹配即可调用
{cout << "void f(int)" << endl;
}void func(int*)
{cout << "void fx(int*)" << endl;
}int main()
{func(0);func(NULL);//会调用第一个函数func((int*)NULL);//调用第二个//#define nullptr ((void*)0)func(nullptr);//nullptr类型是void*return 0;
}

程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的
初衷相悖。

在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器
默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void
*)0。所以在(C++11)引入了nullptr表示空指针。#define nullptr ((void*)0)

注意:

  1.  在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3.  为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr

本篇结束。 

http://www.yayakq.cn/news/132856/

相关文章:

  • 珠海网站开发价格郑州网站设计制作
  • 无锡市建设局一号通网站dedecms更改网站logo
  • 网站设计编程特效音网站
  • 网站备案需要多久如何做微信公众号
  • 微商如何做网站引流网站排版代码
  • 网站开发人员工资西地那非使用三大忌
  • 温岭市建设规划局网站图书馆门户网站建设有哪些公司
  • 郑州春蕾网站建设小内存wordpress
  • 重庆网站建设论坛做外贸如何分析客户网站
  • 毕业设计做网站怎样做特别一点h5多人同时交互
  • 洛阳做网站汉狮网络家用电脑可以做网站服务器
  • 哈尔滨网站建设论坛广东营销式网站
  • 可信的品牌网站建设100部看黄禁用免费入口
  • 凡科网站做的作品如何发布wordpress 如何使用php版本号
  • 建设厅网站怎么查询安全员c考试成绩沈阳高端网站制作公司哪家好
  • 外贸免费自助建站平台wordpress关闭多版本
  • 那家公司做网站惠阳做网站
  • 国内网站开发公司网站logo怎么改
  • 闻喜网站建设做企业的网站的如何推广
  • 领先的手机网站设计山西网站建设推广
  • iis网站重定向设置古镇小企业网站建设
  • html5 素材网站制作网页可以有效控制什么的位置
  • 天津网站建设 seo做一个企业网站需要多长时间
  • 一流的上海网站建设wordpress首页添加登录
  • 网页模版网站动漫制作专业相近专业
  • 甘肃省建设厅官方网站张睿鲜花网站的数据库建设
  • 权威的公司网站制作资阳网站建设方案
  • 做网站互联网公司有哪些wordpress企业版主体
  • 帮忙做文档的网站卖渔具的亲戚做网站
  • 小学文化学网站开发长网络推广