【C++基础(四)】内联函数和auto关键字

简介: 【C++基础(四)】内联函数和auto关键字

💓博主CSDN主页:杭电码农-NEO💓


⏩专栏分类:C++初阶之路


🚚代码仓库:NEO的学习日记🚚


🌹关注我🫵带你学习C++

  🔝🔝



1. 前言

本章重点:

本节着重讲解内联函数的概念
和使用方法,并且介绍auto关键字,
拓展一个C++的范围for(只做了解)


2. 内联函数概念

基本概念:

  • 被inline修饰的函数被称为内联函数
  • 编译器会在编译时将内联函数展开
  • 展开后,没有函数调用建立栈帧的开销
  • 内联函数可以提升程序运行效率

举例说明:

inline int Add(int left, int right)
{
  return left+right;
}

这就是一个内联函数
它的汇编代码可以简单看一下:

函数栈帧的创建与销毁中可知

调用一个函数,开辟栈帧时需要call指令

而这里并没有call指令出现

可见内联函数和普通函数确实有不同

对比说明:普通函数

int Add(int left, int right)
{
  return left+right;
}

它的汇编代码如下:

很明显这里使用了call指令


3. 内联函数的特性

特性:

  1. inline是一种以空间换时间的做法
    如果编译器将函数当成内联函数处理
    在编译阶段,会用函数体替换函数调用

缺陷:可能会使目标文件变大
优势:减少调用开销,提高运行效率


  1. inline对于编译器而言只是一个建议
    若一个函数代码很长
    则编译器不会将它变成内联

在《C++prime》中曾这样写到:


  1. 一般来说,函数代码在10行及以内时
    这时编译器会将它优化为内联函数
    有些编译器是在30行以内

综上所述:

定义函数为内联时
应当检查函数代码行数是否足够少


  1. 内联函数的定义和声明不能分开
    因为inline被展开后
    就没有函数地址了,链接时会找不到

内联函数的一些性质可以
在某些函数使用宏替换的地方
将函数定义为内联,也是同样的效果


4. auto关键字

在学习C++到后期的时候

经常会遇见类似于下面这种代码:

__list_iterator<InputTterator>::iterator it = tmp.begin();
• 1

这段代码看起来非常难理解

但事实上它和定义一个整型是一个意思

就是在定义一个变量

你可能会问:这和auto有啥关系?

auto是一个类型,类似于int,char

但是这个类型是由编译器自己推导出来的

什么意思?,举个例子:

int a = 10;
auto b = a;
auto c = 'a';

由于a是int类型的,将a的值赋值给b
编译器就推导出b的类型也是int
同理可得,c的类型就是char

了解了auto的用法后,来化简代码:

__list_iterator<InputTterator>::iterator it = tmp.begin();
//化简后
auto it = tmp.begin();

这两句代码意思相同
这极大的方便了我们的使用!


5. auto的使用规则

5.1 对指针和引用的区别

  1. 对指针来说*可有可无

请看以下代码:

int x = 10;
auto a = &x;
auto* b = &x;

a的类型是int*,此时的auto是int*

b的类型是int*,此时的auto是int

所以对于对象是指针来说

在使用auto时加不加*都无所谓

  1. 对引用来说必须加上&

请看以下代码:

int x = 10;
auto& c = x;
auto d = x;

c的类型是int的引用,此时的auto是int

d的类型是int,此时的auto是int

假设你想定义一个引用变量

请务必加上引用&符号


5.2 一行多次定义的场景

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

比如:

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

事实上,当第一个变量被推导成int后
第二个变量默认也是int.
但是int类型不能存放double类型的值


5.3 auto无法使用的场景

  1. auto无法作为函数参数
void TestAuto(auto a)
{
  //...
}

此处编译器无法对a的实际类型进行推导

  1. auto无法用于声明数组
int a[] = {1,2,3};
auto b[] = {4,5,6};

感觉上,数组中都是整型

那么auto应该会自动识别为整型

但是实际上这样做是不行的,详情请看:

英文文献


6. 基于范围的for循环

C++11中支持这样遍历数组:

int arr[] = {1,2,3,4,5,6};
for(auto e : arr)
{
  cout<<e <<" ";
}

其中的for循环的框架就叫做范围for

它可以这样理解:

并且范围for是可读可写的!

int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array)
{
   e *= 2;
}

只需要将e的类型变为引用
就可以修改数组中元素

注:中间的:是范围for的规定写法,没有特殊意义

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


7. 总结以及拓展

本节的所有内容旨在为后面的C++
学习打基础,C++学习一环紧扣一环
环环都不能掉队!

拓展:

是不是感觉C++的范围for非常神奇?
但是实际上它是一个非常笨比的实现
它依赖一个叫迭代器的东西

底层实现上
必须有一个自定义函数叫begin()才能
满足范围for,就算你实现的功能和begin
函数一样,但是名字不一样
也不支持范围for,比如Begin

虽然C++后期的学习也会提到范围for

但是大家有兴趣可以提前了解

详情可以参考这篇文章:

C++ 中不同类型的基于范围的 for 循环迭代器


🔎 下期预告:类和对象(上) 🔍



相关文章
|
2月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
3月前
|
安全 程序员 编译器
C++ 11新特性之auto和decltype
C++ 11新特性之auto和decltype
44 3
|
2月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
2月前
|
程序员 C++ 开发者
C++入门教程:掌握函数重载、引用与内联函数的概念
通过上述介绍和实例,我们可以看到,函数重载提供了多态性;引用提高了函数调用的效率和便捷性;内联函数则在保证代码清晰的同时,提高了程序的运行效率。掌握这些概念,对于初学者来说是非常重要的,它们是提升C++编程技能的基石。
23 0
|
3月前
|
C语言 C++
C++(三)内联函数
本文介绍了C++中的内联函数概念及其与宏函数的区别。通过对比宏函数和普通函数,展示了内联函数在提高程序执行效率方面的优势。同时,详细解释了如何在C++中声明内联函数以及其适用场景,并给出了示例代码。内联函数能够减少函数调用开销,但在使用时需谨慎评估其对代码体积的影响。
|
4月前
|
存储 编译器 C++
【C++关键字】auto的使用(C++11)
【C++关键字】auto的使用(C++11)
|
14天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
25 2
|
20天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
54 5
|
26天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
56 4
|
27天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
65 4