C++入门之内联函数与auto、nullptr、for关键字

宏函数:宏函数是一种在编译预处理阶段展开的宏定义,用于在代码中进行简单的文本替换。宏函数可以通过宏定义来定义,并且可以带有参数。在宏函数的定义中,参数列表是一个用逗号分隔的参数序列,替换文本是宏函数被展开后要替换的文本。宏函数的使用类似于函数调用,可以在代码中使用宏函数名和参数列表来调用宏函数。在编译预处理阶段,编译器会将宏函数调用展开为相应的替换文本。

宏函数的作用:

函数调用涉及函数调用的开销,包括保存和恢复现场、参数传递、返回值处理等。如果函数调用次数过多,这些开销会累积起来,导致程序的运行速度变慢,更加严重的话会导致栈溢出。C语言中为了防止同一个简单的函数调用次数过多导致性能下降或者栈溢出,就会用宏函数。

可以看出当数据量大时,很明显性能上的差距,更不要说递归下对栈空间的损耗。

宏函数的作用:

宏函数的作用是在编译预处理阶段对代码进行简单的文本替换。它可以用于以下几个方面:

代码重用:宏函数可以定义一段常用的代码片段,并在需要的地方进行调用。这样可以减少重复编写代码的工作量,并提高代码的可维护性。

简化代码:宏函数可以用来简化代码,例如定义一个宏函数来计算一个数的平方,可以减少重复的代码编写。

条件编译:宏函数可以用于条件编译,通过定义和使用宏函数,可以根据不同的条件编译不同的代码片段。

但是,宏函数在展开时是简单的文本替换,没有类型检查和语法检查。因此,在使用宏函数时需要谨慎,确保宏函数的替换结果符合预期。另外,宏函数的展开可能会导致代码的可读性下降,所以在使用宏函数时应该权衡代码的可读性和简洁性。

因此,C++对此做出了改进,引进了内联函数,关键字inline。

内联函数是一种编译器优化技术,它的原理是将函数的代码插入到调用该函数的地方,而不是进行函数的调用。这样可以减少函数调用的开销,包括参数传递、栈帧的创建和销毁等。内联函数的原理可以简单地理解为在编译时将函数调用的地方替换成函数的代码。当编译器遇到内联函数的调用语句时,它会将函数的代码直接插入到调用的地方,就像是将函数的代码复制粘贴到调用的地方一样。这样就避免了函数调用的开销,提高了程序的执行效率。

为了将函数内联,编译器通常需要满足一些条件:

1、函数的定义不能太复杂,否则内联展开后的代码会变得冗长,可能会导致代码膨胀和缓存失效,使得可执行程序变大。

2、函数不能包含递归调用或循环调用,否则无法进行内联展开。

3、内联函数应该声明实现一,如果在内联函数的声明处没有实现函数体,会导致链接错误。这是因为编译器在编译期间需要知道函数的具体实现,以便进行内联展开或者生成函数的调用代码。当我们在某个源文件中使用了一个内联函数的声明时,编译器会期望在其他地方找到该内联函数的实现。如果找不到实现,编译器会报错,提示找不到对应的函数定义。这是因为内联函数的声明只是告诉编译器该函数可以进行内联展开,但并不提供具体的函数实现。为了解决这个问题,我们需要在某个源文件中提供内联函数的实现。通常的做法是将内联函数的定义放在头文件中,以便在多个源文件中进行使用。这样,编译器在编译每个源文件时都能够看到内联函数的实现,从而进行内联展开或者生成函数的调用代码。

注意:编译器对于是否将函数进行内联展开有最终决定权,即使加上了inline关键字,但如果内联函数过长或者是递归函数,编译器也可以选择不进行内联展开。

需要注意的是,内联函数并不是绝对比普通函数效率高的,它们的性能差距取决于具体的代码场景和编译器的优化能力。在一些情况下,内联函数可能会比普通函数更低效,因为内联函数可能导致代码膨胀和缓存失效。因此,在实际编程中,应根据具体情况选择合适的函数形式。

auto关键字:随着程序越来越复杂,程序中的类型也越来越复杂,经常体现在:类型难于拼写,含义不明确容易出错。而typedef也会遇到难题。

当我们定义了一个指向常量字符的指针后,如果我们没有为其分配内存空间,那么指针就没有指向有效的内存地址,这会导致程序在访问指针所指向的内存时出现错误。编译器会在编译阶段对这种错误进行检查,并报告错误信息。这样可以帮助我们在编译时发现潜在的问题,避免在运行时出现不可预测的错误。但是,定义一个指向常量字符指针的指针,虽然没有进行初始化,指向未知地址,但是它不需要为指针分配内存空间。

因此,auto出现让编译器自动推导变量的类型。

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

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

auto与指针结合不结合的意义相等。

语法糖:for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,但是迭代范围必须明确。

NULL和nullptr区别:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昨日青空。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值