004 C++基础篇

2023-11-08

前言

大家好,本文将会为您带来内联函数,auto关键字,基于范围的for循环,指针空值nullptr相关知识

一、内联函数

什么是内联函数


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

内联函数的运用

inline int Add(int a, int b)
{
       return a + b;
}
int main()
{
       int ret = 0;
       ret = Add(1, 2);
       return 0;
}
在观察有无inline的差异时,我们首先应做以下配置(在Debug模式下)

鼠标右键点击项目
在这里插入图片描述
点击属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以下是程序加上inline与不加inline的反汇编(待程序调试起来,鼠标右键点击反汇编)

不加inline
在这里插入图片描述

加inline
在这里插入图片描述

我们可以观察到不加inline会有call语句去调用函数,而加inline后call语句则被替换成了函数体(mov,add,mov)


inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用
缺陷:会使目标空间变大,优势:少了调用开销,提高程序运行效率

内联函数的局限性


1、内联机制用于规模较小,流程直接、频繁调用的函数。很多编译器都不支持内联递归函数,当一个规模较大的函数可能将不会在调用点内联地展开
2、inline不建议声名与定义分离
以下程序如果调用f(),则会出现错误

在这里插入图片描述

func.cpp
#include "Func.h"	
void f(int i)
{
	cout << i << endl;
}
void fx()
{
	f(1);  //在此文件里有f的声名和定义,不用call f()地址,直接展开
}

func.h
#include <iostream>
using namespace std;
inline void f(int i);

main.cpp
int main()
{
	error:f(1);//此语句虽然是内联,但是展不开,因为.h文件里只有声名
	//只能去链接,但是内联函数不生成指令进入符号表。符号表里没有该函数的地址,如果声名与定义分离,就会出现链接错误
	fx();//如果调用fx,便可以间接展开f的内联,原因是在func.cpp中,f函数的声名(头文件)和定义都存在
	return 0;
}


二、auto关键字( C++11 )

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量 在C++11及之后的版本中,auto关键字被重新定义为类型推断的工具。使用auto可以让编译器根据变量的初始化表达式来推断其数据类型,从而省略了显式指定变量类型的过程。

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

int main()
{
	int x = 1;
	auto& a = x; 
	auto b = 1.1;
	auto c = 'c';
	auto d = &a;
	auto* e = &a;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	cout << e << endl;
	return 0;
}

auto不能推导的场景

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

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


2、auto不能作为函数的参数

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


3、auto不能直接用来声明数组

void TestAuto()
{
    int a[] = {1,2,3};
    auto b[] = {456};
}

三、基于范围的for循环( C++11 )

如果要遍历一个数组,对于程序员来说,说明循环的范围是没有太大必要的,因此C++11中引入了基于范围的for循环。

由两部分组成:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

int main()
{
	int array[] = { 1,2,3,4,5,6,7,8,9 };
	for (auto a : array)
	{
		cout << a << " ";
	}
	return 0;
}

在这里插入图片描述

四、指针空值nullptr( C++11 )

在C++98中,我们通常使用NULL来表示空指针 NULL实际上是一个宏,在传统的C头文件(stddef.h)中,如下:
#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦
NULL是一个宏定义,其值为0,因此可以被隐式地转换为整型。例如在重载函数时,如果有一个函数接受指针参数,另一个函数接受整型参数,传入NULL时可能会导致调用错误的函数
在C++11中,引入了nullptr关键字,用于表示空指针常量。nullptr是一个字面量,它的类型是nullptr_t。nullptr的引入主要是为了解决NULL的一些问题和不明确性。

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

小结

如果本文存在遗漏或错误的地方,还请您能够指出,祝您天天开心啦!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

004 C++基础篇 的相关文章

随机推荐

  • [JavaWeb]完美解决IDEA(2022)新建没有Servlet选项(无法访问Servlet 404问题)

    IntelIJ IDEA在2022版本中更新和2021版本界面差距还是比较大的 你们是否有遇到过以下问题呢 右键包没有新建Servlet的选项 WebServlet 404 web xml配置映射时
  • cross gcc linux gcc 区别,深入理解交叉编译(Cross Compile)

    深入理解交叉编译 Cross Compile 首先你要了解一下 三个名词 build haost target 和三元组 build 构建 gcc 编译器的平台系统环境 编译该软件使用的平台 host 是执行 gcc 编译器的平台系统环境
  • SVO、vinsmono、 OKVIS系统比较

    几个经典视觉slam系统的比较 SVO 高翔链接 https www zhihu com question 39904950 answer 138644975 处理的各个线程 tracking部分 frame to frame frame
  • 基础算法题——斐波那契(快速求幂、斐波那契特性、矩阵)

    基础算法题 斐波那契 做题心得 这道算法题花了我几乎一天的时间才弄懂 不得不说我还是太菜了 该算法题主要考查了对斐波那契数列的理解 矩阵与斐波那契结合 快速求幂 在看了数篇博客后我才慢慢对矩阵 快速求幂有所了解 由于是初步接触这类题型 如果
  • unity 获取网络时间

    网络时间 using System using System Collections using System Collections Generic using UnityEngine using UnityEngine Networki
  • C++ 逗号运算符

    逗号运算符 comma operator 含有两个运算对象 按照从左向右的顺序依次求值 对于逗号运算符来说 首先对左侧的表达式求值 然后将求值结果丢弃掉 逗号运算符真正的结果是右侧表达式的值 如果右侧运算对象是左值 那么最终的求值结果也是左
  • 大数据FLINK实时数仓项目实战

    一 FLINK实时数仓项目简介 1 普通实时计算与实时数仓比较 普通的实时计算优先考虑时效性 所以从数据源采集经过实时计算直接得到结果 如此做时效性更好 但是弊端是由于计算过程中的中间结果没有沉淀下来 所以当面对大量实时需求的时候 计算的复
  • 串口通信(RS232的C程序)

    Bioscom使用注意 串口接线方式为4 6 7 8分别短接 仅此函数要求 否则会造成只能接受无法发送数据 函数返回值错误 函数名 bioscom 功 能 操作port指定的RS232异步通讯口 用 法 int bioscom int cm
  • 剑指 Offer 25. 合并两个排序的链表

    合并两个排序的链表 思路 题解 package swordPointingToTheOffer public class ListNode int val ListNode next ListNode int x val x public
  • C语言:前 n 项求和

    前 n 项求和 算法思路 1 前n项求和由于第一项和最后一项都已知适合用for循环 2 当n趋于无穷时 调和数列的极限趋于无穷 代码如下 include
  • Eclipse 3.4+MyEclipse 6.01+MyEclipse 6.01注册机+Eclipse 3.1.1汉化包+Myeclipse6.0使用教程官方下载地

    Eclipse 3 4 MyEclipse 6 01 MyEclipse 6 01注册机 Eclipse 3 1 1汉化包 Myeclipse6 0使用教程官方下载地 2007年10月29日 星期一 05 30 P M 都是供WINDOWS
  • LeetCode:392(Python)—— 判断子序列(简单)

    判断子序列 概述 给定字符串 s 和 t 判断 s 是否为 t 的子序列 字符串的一个子序列是原始字符串删除一些 也可以不删除 字符而不改变剩余字符相对位置形成的新字符串 例如 ace 是 abcde 的一个子序列 而 aec 不是 输入
  • Leetcode刷题笔记0624(回文字符串)

    解题思路 1 首先考虑用双指针 一头一尾依次遍历 遇到相等的l 和r 进入下一层循环 2 遇到不相等的记录值count 1 判断l 与r是否相等 l与r 是否相等 否则直接返回false 形成代码 class Solution public
  • F轮融资3.6亿美元,Keep能撑起20亿美元的估值吗?

    高喊着 自律给我自由 的keep 在自由的道路上不断奔跑 去年12月底 keep完成了F轮3 6亿美元融资 本轮融资由软银愿景基金领投 高瓴资本 蔻图资本跟投 成为近年国内运动科技领域融资的最大金额 keep估值成功站上20亿美元大关 这距
  • STM32 ST-LINK Utility安装及使用

    TM32 ST LINK Utility集成开发环境的安装比较简单 基本上就是一路Next下去 还是按照常规安装教程 截图 讲述一下吧 以上面下载的 STM32 ST LINK Utility v4 0 0 setup exe 软件为例讲述
  • 安装SQL Server2012报Microsoft.NET Framework4无法安装错误解决方案

    今天在安装SQL Server2012版本时 在最后出现 没有安装Microsoft NET Framework4 请安装这个继续安装SQLServer2012 于是就重官网下载Microsoft NET Framework4进行安装出现如
  • homebrew安装mysql及修改配置

    安装mysql数据库5 7 5前后版本有所差异 以前的版本会在安装的时候要去输入密码 5 7 6 版本会在安装的时候随机生成一个密码 用图形界面化安装的时候会显示密码 而用 brew install mysql命令安装的话 就不会显示密码了
  • Volocopter将在新加坡推出空中的士服务;铂金资本72亿美元收购海航旗下英迈

    今日看点 铂金资本 Platinum Equity 将以72亿美元收购海航旗下的英迈 Volocopter将在新加坡推出空中的士 希尔顿与锦江集团续签合作协议 将在华开逾600家希尔顿欢朋酒店 爱立信携手意大利电信及高通公司基于5G毫米波创
  • c# ThoughtWorks 生成二维码

  • 004 C++基础篇

    前言 大家好 本文将会为您带来内联函数 auto关键字 基于范围的for循环 指针空值nullptr相关知识 一 内联函数 什么是内联函数 以inline修饰的函数叫做内联函数 编译时C 编译器会在调用内联函数的地方展开 没有函数调用建立栈