C++17中的内联变量

      在C++11中:
      (1).声明为constexpr的函数隐式地是内联函数;
      (2).deleted函数隐式地是一个内联函数。
      在内联函数中:
      1.所有函数定义中的函数局部静态对象(function-local static object)在所有翻译单元之间共享(它们都引用一个翻译单元中定义的同一对象)。
      2.所有函数定义中定义的类型在所有翻译单元中也相同。
      inline关键字的最初目的是向优化器指示函数的内联替换优先于函数调用,即不执行函数调用CPU指令将控制权转移到函数体,而是执行函数的副本即函数体在不生成调用的情况下执行。这避免了函数调用(传递参数并检索结果)产生的开销,但可能会导致更大的可执行文件,因为函数的代码必须重复多次。
      由于关键字inline的含义是非绑定的(non-binding),因此编译器可以自由地对任何未标记为内联的函数使用内联替换,并且可以自由地生成对任何标记为内联的函数的函数调用。

      C++17引入了内联变量,即允许在多个文件中定义的变量。内联变量的工作方式与内联函数类似,并且具有相同的要求(编译器必须能够在使用该变量的任何地方看到相同的完整定义)。

      内联说明符(inline specifier)在具有静态存储持续时间(static storage duration)的变量(静态类成员或命名空间范围内的变量)的decl-specifier-seq(declaration specifiers)中使用时,将该变量声明为内联变量。
      声明为constexpr的静态成员变量(但不是命名空间范围内的变量)隐式地是内联变量

      C++的两种链接方式:外部链接(External Linking)和内部链接(Internal Linking)
      1.外部链接:函数或变量可以在其它翻译单元中使用。默认情况下,在C++中定义的函数和全局变量都具有外部链接属性。
      2.内部链接:函数或变量只能在定义它的翻译单元中使用。

      内联函数或内联变量(inline function or inline variable)具有以下属性:
      1.内联函数或内联变量的定义必须在访问它的翻译单元(translation unit,源代码文件如.cpp)中可访问
      2.具有外部链接(external linkage)(例如未声明为静态)的内联函数或内联变量具有以下附加属性:
      (1).程序中可能存在多个内联函数或内联变量的定义,只要每个定义出现在不同的翻译单元中(different translation unit)并且(对于非静态内联函数和内联变量)所有定义都是相同的。例如,内联函数或内联变量可以定义在包含在多个源文件中的头文件中。
      (2).它必须在每个翻译单元中声明为内联。
      (3).每个翻译单元都有相同的地址(same address).

      命名空间范围内的内联const变量默认具有外部链接(与非内联、非易失性、const限定(non-inline non-volatile const-qualified)变量不同)。

      因为函数的关键字inline的含义开始意味着"允许多个定义"而不是"首选内联",所以该含义被扩展到内联变量。在现代C++中,内联已演变为"允许多个定义"的意思

      内联变量消除了将C++代码打包为仅含头文件库的主要障碍(Inline variables eliminate the main obstacle to packaging C++ code as header-only libraries)。

      内联变量在未声明为静态时具有外部链接.
      如果内联变量有多个定义,编译器会在需要时选择其中一个定义.
      与内联函数不同,内联变量可以具有静态存储持续时间(static storage duration)。如果内联变量是在类范围内定义的,则它的行为类似于静态成员变量。此类成员变量可以在类内部初始化
      内联变量在所有翻译单元中具有相同的内存地址。
      C++17允许在不同的翻译单元中对内联变量进行多个定义,并且每个翻译单元将拥有自己的变量副本。
      内联变量默认具有外部链接。如果我们想定义一个具有内部链接的内联变量,我们可以使用静态说明符。
      当我们在全局变量上使用inline关键字时,我们不需要在其他地方将它们定义为"extern"。对于静态成员变量,我们不需要在类外部定义它们
      根据一次定义原则(ODR, One Definition Rule),一个变量或实体的定义只能出现在一个编译单元内----除非该变量或实体被定义为inline的。

      内联变量和thread_local:通过使用thread_local你可以为每个线程创建一个内联变量

      注意:
      (1).如果具有外部链接的内联函数或内联变量在不同的翻译单元中定义不同,则程序格式错误(ill-formed),无需诊断。
      (2).内联说明符不能与块作用域(在另一个函数内)的函数或变量声明一起使用。
      (3).内联说明符无法重新声明已在翻译单元中定义为非内联的函数或非内联的变量。
      (4).隐式生成的(implicitly-generated)成员函数以及在其第一个声明中声明为默认的(defaulted)任何成员函数都是内联的,就像类定义中定义的任何其他函数一样。
      (5).如果在不同的翻译单元中声明内联函数,则每个翻译单元末尾的累积默认参数集必须相同(the accumulated sets of default arguments must be the same at the end of each translation unit)。

      以下为测试代码:

      1. inline.hpp:此头文件会被多个.cpp文件include,若不带inline,会编译不过

class InlineVariable {
public:inline static int var{ 10 }; // 不带inline,则只能在类外初始化;即使在类外初始化,如果被多个cpp文件包含也会error;带inline后,即使被多个cpp文件包含也OKconst char* csdn_addr{ "https://blog.csdn.net/fengbingchun/" };static constexpr int num{ 6 }; // 对于静态成员,constexpr修饰符隐含着inline,等价于: inline static constexpr int num{ 6 };inline static std::string name{ "Messy_Test" }; // 整个程序中只有一个inline static thread_local int count{ 1 }; // 每个线程有一个std::string city{ "BeiJing" }; // 每个实例有一个
};inline InlineVariable inline_variable; // 不带inline,则会报重复定义;带inline后,即使被多个cpp文件包含也OK
inline thread_local InlineVariable inline_variable2; // 每个线程一个对象

      2. inline.cpp:

int test_inline_variable_1()
{std::cout << "var: " << InlineVariable::var << "\n";std::cout << "csdn addr: " << inline_variable.csdn_addr << "\n";std::cout << "num: " << InlineVariable::num << "\n";return 0;
}

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Messy_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/589324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【c++————————构造函数和析构函数】

【c————————构造函数和析构函数】 欢迎阅读新一期的c模块————构造函数和析构函数 ✒️个人主页&#xff1a;-Joker- &#x1f3f7;️专栏&#xff1a;C &#x1f4dc;代码仓库&#xff1a;c_code &#x1f339;&#x1f339;欢迎大佬们的阅读和三连关注&#xff0c…

Dependency Track:智能组件分析平台。

Dependency Track:智能组件分析平台。 ############################# 免责声明:工具本身并无好坏,希望大家以遵守《网络安全法》相关法律为前提来使用该工具,支持研究学习,切勿用于非法犯罪活动,对于恶意使用该工具造成的损失,和本人及开发者无关。 ################…

Linux | 解决问题Ubuntu重启无法进入系统以及网络无法连接【图文详解】

Ubuntu18.04重启无法进入系统&#xff0c;重开后如图 一直在加载系统内核4.15.0-213-generic,无法加载 错误原因 原本的系统是Ubuntu16.04,使用命令升级到Ubuntu18.04版本&#xff0c;升级重启后&#xff0c;远程无法连接&#xff01; 错误解决 第一步&#xff1a;进入GRUB…

AIGC入门系列1:感性的认识扩散模型

1、序言 大家好&#xff0c;欢迎来到AI手工星的频道&#xff0c;我是专注AI领域的手工星。AIGC已经成为AI又一个非常爆火的领域&#xff0c;并且与之前的AI模型不同&#xff0c;AIGC更适合普通人使用&#xff0c;我们不仅可以与chatgpt对话&#xff0c;也能通过绘画模型生成想…

使用ASP.NET MiniAPI 调试未匹配请求路径

本文将介绍如何在使用ASP.NET MiniAPI时调试未匹配到的请求路径。我们将详细讨论使用MapFallback方法、中间件等工具来解决此类问题。 1. 引言 ASP.NET MiniAPI是一个轻量级的Web API框架&#xff0c;它可以让我们快速地构建和部署RESTful服务。然而&#xff0c;在开发过程中如…

PACC:数据中心网络的主动 CNP 生成方案

PACC&#xff1a;数据中心网络的主动 CNP 生成方案 文章目录 PACC&#xff1a;数据中心网络的主动 CNP 生成方案PACC算法CNP数据结构PACC参数仿真结果参考文献 PACC算法 CNP数据结构 PACC参数 仿真结果 PACC Hadoop Load0.2 的情况&#xff1a; PACC Hadoop Load0.4 的情况&a…

go slice源码探索(切片、copy、扩容)和go编译源码分析

文章目录 概要一、数据结构二、初始化2.1、字面量2.2、下标截取2.2.1、截取原理 2.3、make关键字2.3.1、编译时 三、复制3.1、copy源码 四、扩容4.1、append源码 五&#xff1a;切片使用注意事项六&#xff1a;参考 概要 Go语言的切片&#xff08;slice&#xff09;是对数组的…

axios的使用及说明

目录 1.说明 2.直接使用 3.封装使用 4.注意 1.说明 官网&#xff1a;Axios 实例 | Axios中文文档 | Axios中文网 Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使…

Java超高精度无线定位技术--UWB (超宽带)人员定位系统源码

UWB室内定位技术是一种全新的、与传统通信技术有极大差异的通信新技术。它不需要使用传统通信体制中的载波&#xff0c;而是通过发送和接收具有纳秒或纳秒级以下的极窄脉冲来传输数据&#xff0c;从而具有GHz量级的带宽。 UWB&#xff08;超宽带&#xff09;高精度定位系统是一…

java零拷贝zero copy MappedByteBuffer

目录 调用操作系统的 mmap 未使用 mmap 的文件通过网络传输的过程 使用 mmap 的文件通过网络传输的过程 使用例子 调用操作系统的 sendfile() 在 java 中的具体实现 mmap的优劣 mmap 的不足 mmap 的优点 mmap 的使用场景 对于零拷贝&#xff08;zero copy&#xff09…

C语言实验4:指针

目录 一、实验要求 二、实验原理 1. 指针的基本概念 1.1 指针的定义 1.2 取地址运算符&#xff08;&&#xff09; 1.3 间接引用运算符&#xff08;*&#xff09; 2. 指针的基本操作 2.1 指针的赋值 2.2 空指针 3. 指针和数组 3.1 数组和指针的关系 3.2 指针和数…

【Linux】内核编译 镜像制作

文章目录 一、Ubuntu内核编译1.1 为什么自己编译内核1.2 Ubuntu 内核源码下载1.21 内核的作用1.22 Linux内核与ubuntu内核1.23 Ubuntu内核源码获取 1.3 在Windows系统下编译ubuntu内核1.4 在Linux系统下编译ubuntu内核 二、镜像制作 一、Ubuntu内核编译 1.1 为什么自己编译内核…

用LCD循环右移显示“Welcome to China“

#include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 sbit RSP2^0; //寄存器选择位&#xff0c;将RS位定义为P2.0引脚 sbit RWP2^1; //读写选择位&#xff0c;将RW位定义为P2.1引脚 sbit EP2^2; //使能…

Debezium日常分享系列之:向 Debezium 连接器发送信号

Debezium日常分享系列之&#xff1a;向 Debezium 连接器发送信号 一、概述二、激活源信号通道三、信令数据集合的结构四、创建信令数据集合五、激活kafka信号通道六、数据格式七、激活JMX信号通道八、自定义信令通道九、Debezium 核心模块依赖项十、部署自定义信令通道十一、信…

【C# 技术】 C# 常用排序方式——自定义数据排序

C# 常用排序方式——自定义数据排序 前言 在最近的项目中经常会对C#中的数据进行排序&#xff0c;对于基本数据类型&#xff0c;其排序方式比较简单&#xff0c;只需要调用内置算法即可实现&#xff0c;但对于自定义数据类型以及自定义排序规则的情况实现起来就比较麻烦&…

区分LR(0),SLR(1),LR(1)和LALR(1)

目录 对于LR(0)文法&#xff1a; 对于SLR(1)文法&#xff1a; 对于LR(0)和SLR(1)文法&#xff1a; 对于LR(1)和SLR(1)文法&#xff1a; 对于LALR(1)文法&#xff1a; 例题1&#xff1a; 例题2&#xff1a; 例题3&#xff1a; 例题4&#xff1a; 这几个文法大致的步骤都…

推荐几个贼有意思的开源项目!

这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、Java、Go、C/C、Swift...让你在短时间内感受到开源的魅力&#xff0c;对编程产生兴趣&#xff01; C 项目 1、kilo&#xff1a;不到 1 千行代码实现的迷你文本编辑器。该项…

Portraiture4.1汉化版PS磨皮插件(支持原生m1芯片m2)

Portraiture汉化版PS磨皮插件。本期推荐一款全新ai算法ps2024中文汉化版ps磨皮插件Portraiture 4.1.2美颜滤镜安装包最新版ps调整肤色插件! 全新Portraiture 4.1.2版本PS人像修图美颜磨皮插件&#xff0c;升级AI算法&#xff0c;并支持多人及全身磨皮美化模式&#xff0c;推荐…

【嵌入式开发 Linux 常用命令系列 7.3 -- linux 命令行数值计算】

文章目录 linux 命令行数值计算使用 awk使用 bc 命令使用 Bash 的内置算术扩展使用 expr脚本命令实现 linux 命令行数值计算 在 Linux 命令行中&#xff0c;您可以使用多种方法来执行基本的数学运算。以下是一些示例&#xff1a; 使用 awk awk 是一个强大的文本处理工具&…

【C#】知识点实践序列之Lock的输出多线程信息

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂之知识点实践序列》文章。 2023年第2篇文章&#xff0c;此篇文章是C#知识点实践序列之Lock知识点&#xff0c;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 本篇在Lock锁定代码…