跨文件的代码组织必须处理模板函数和内联

2024-01-01

我正在维护一个大型模板类库,它们基于以下任意一个执行代数计算float or double类型。许多类都有访问器方法(getter 和 setter)和其他运行少量代码的函数,因此当编译器找到它们的定义时,需要将这些函数限定为内联。相比之下,其他成员函数包含复杂的代码,因此最好调用而不是内联。

函数定义的很大一部分位于标头中,实际上位于标头包含的 .inl 文件中。但也有许多类的函数定义通过显式实例化而愉快地存在于 .cpp 文件中float and double,这对于图书馆来说是一件好事(here https://stackoverflow.com/questions/2351148/explicit-instantiation解释了原因)。最后,有相当多的类的函数定义分散在 .inl 文件(访问器方法)和 .cpp 文件(构造函数、析构函数和繁重计算)中,这使得它们都非常难以维护。

仅当我知道一种可靠的方法来防止某些函数被内联时,我才会将所有类实现放在 .inl 文件中,或者在 .cpp 文件中,如果inline关键字可能强烈建议编译器内联某些函数,当然,事实并非如此。我确实希望库中的所有函数定义都驻留在 .cpp 文件中,但由于访问器方法在整个库中广泛使用,因此我必须确保它们在引用时内联,而不是调用。

因此,在这方面,我的问题是:

  1. 用 标记模板函数的定义是否有意义inline鉴于我最近了解到的事实here https://stackoverflow.com/questions/11416747/multiple-definitions-of-a-non-template-class-vs-a-template-class,无论它是否标记为内联,编译器都会自动将其限定为内联inline or not?

  2. And 最重要的是,因为我想收集模板类的所有成员函数的定义一起在一个文件中,最好是 .inl 或 .cpp(在 .cpp 的情况下使用显式实例化)still能够提示编译器(MSVC 和 GCC)应该内联哪些函数and这不应该,确定这样的事情是否可以通过模板函数实现,我怎样才能实现这个目标,或者,如果真的没有办法(我希望有),最佳的折衷方案是什么?

----------

EDIT1:我知道inline关键字只是建议编译器内联函数。

EDIT2:我确实知道。我喜欢向编译器提出建议。

EDIT3:我还是知道的。这不是问题的重点。

----------

鉴于一些新的信息,还有第三个问题与第二个问题同时出现。

3.如果现在的编译器如此聪明,他们可以更好地选择应该内联哪些函数以及应该调用哪些函数and能够进行链接时代码生成和链接时优化,这有效地允许他们在链接时查看位于 .cpp 的函数定义,以决定其内联或调用的命运,那么也许一个好的解决方案就是简单地移动所有定义到各自的 .cpp 文件中?

----------

那么结论是什么呢?

首先,我感谢 Daniel Trebbien 和 Jonathan Wakely 的结构化且有理有据的回答。两者都投了赞成票,但必须只选择一个。然而,给出的答案都没有为我提供可接受的解决方案,因此所选择的答案恰好是对我做出最终决定稍有帮助的答案,接下来将向感兴趣的人解释其详细信息。

好吧,由于我一直更看重代码的性能,而不是维护和开发的方便程度,因此在我看来,最可接受的折衷方案是移动每个的所有访问器方法和其他轻量级成员函数。将模板类放入相应标头包含的 .inl 文件中,并用以下标记标记这些函数inline尝试为编译器提供良好的提示(或内联强制的关键字),并将其余函数移至相应的 .cpp 文件中。

将所有成员函数定义都放在 .cpp 文件中会阻碍轻量级函数的内联,同时会引发链接时优化的一些问题,正如 MSVC 的 Daniel Trebbien(在较早的开发阶段)和 GCC 的 Jonathan Wakely 所确定的那样(目前的发展阶段)。将所有函数定义都放在头文件(或 .inl 文件)中并不比将每个类的实现分类到 .inl 和 .cpp 文件中的总体好处加上此决定的额外副作用:它将确保只有原始访问器方法的代码对库的客户端可见,而更多有趣的东西隐藏在二进制文件中(确保这不是主要原因,但是,对于熟悉软件库的任何人来说,这一点都是显而易见的)。任何不需要由库的包含文件公开并由其类私有使用的轻量级成员函数都可以在该类的 .cpp 文件中进行定义,而其声明/定义则包含inline鼓励函数的内联状态(尚不知道关键字是否应该出现在两个位置,或者在这种特殊情况下只出现在一个位置)。


简而言之:将模板代码放在头文件中。使用特定于编译器的forceinline or noinline如果优化器未能就内联做出正确的决定,则使用关键字。


您可以而且应该将模板成员的定义放入头文件中。这确保编译器在发现实际模板参数是什么时可以在使用时访问定义,并且能够执行隐式实例化。

The inline关键字对模板的影响很小,因为模板函数已经免除了单一定义要求(单一定义规则仍然要求所有定义相同)。它向编译器提示该函数应该被内联。您可以省略它,作为编译器不要内联该函数的提示。所以就这样使用它。但优化器仍会考虑其他因素(函数大小)并自行选择内联。

有些编译器有特殊的关键字,比如__attribute__(always_inline) or __declspec(noinline)覆盖优化器的选择。

不过,大多数情况下,编译器足够聪明,不会内联“作为函数调用更有意义的复杂代码”。您不必担心它,只需让优化器完成它的工作即可。

便携式内联控制没有什么好处,因为内联的权衡是非常特定于平台的。优化器应该已经意识到这些特定于平台的权衡,如果您确实觉得需要覆盖编译器的选择,请在每个平台的基础上进行操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

跨文件的代码组织必须处理模板函数和内联 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • 使用 sklearn 通过 Keras 数据生成器绘制混淆矩阵

    Sklearn 明确定义了如何使用自己的分类模型绘制混淆矩阵plot confusion matrix https scikit learn org stable auto examples model selection plot con
  • componentDidUpdate 与 componentDidMount

    当满足以下条件时 我需要确保输入元素获得焦点 DOM 可用 并且属性发生了变化 问题 我需要将我的代码放入两个中吗componentDidUpdate and componentDidMount要不就componentDidUpdate就足
  • 如何在轴标签和图例中的下标中写入文本?

    我有以下轴标签和图例 plt ylabel ratio 2 plt xlabel n 1 plt legend alpha 1 alpha 2 loc best shadow True 在公式周围加上美元符号 plt xlabel n 1
  • 使用 webdriver 与可爱的编辑器交互

    有谁知道我如何使用 webdriver 与可爱的编辑器交互 我想清除文字 下面的代码不起作用 driver switchTo frame 0 driver switchTo activeEle
  • 是否可以在用户不与网络交互的情况下播放音频?我该怎么做呢? [复制]

    这个问题在这里已经有答案了 我需要我的网页在用户不与页面交互的情况下播放音频剪辑 我知道用户体验很差 不应该这样做 但这就是我的客户所要求的 我也知道浏览器已经阻止了这个功能 所以如果有人能给我建议如何 破解 这个规则 例如事件 我将不胜感
  • 如何在 Sphinx 运行时预处理源文件?

    我已经为我的项目设置了 Sphinx 文档 并希望提取源文件的文档字符串并将它们嵌入到最终文档中 不幸的是 Sphinx 不支持源文件的语言 VHDL VHDL 似乎没有 Sphinx 域 所以我的想法如下 挂钩 Sphinx 运行并在 S
  • 如何在maatwebsite中获取excel数组

    我正在尝试使用最新版本将 Excel 文件转换为数组Laravel Excel https github com Maatwebsite Laravel Excel 3 1 9 下面的代码将下载该文件 return Excel downlo
  • 一个图例的两个独特标记符号

    我想在图例下的 红色实心圆圈 符号旁边添加一个 红色实心正方形 符号 我该如何实现这一目标 我更喜欢坚持使用 pyplot 而不是 pylab 下面是我一直在使用的代码 fig plt figure ax1 fig add axes 0 1
  • 条件逻辑在默认的knockout.js 2.0模板引擎下工作吗?

    下面的条件不适用于我的默认模板与 knockout js 2 0 它只是写出 IF 语句 span if data app viewModel admin home paging page span span else a href a i
  • CPU 总使用率 - 多核系统

    我正在使用 xen 并与xen top我得到了 CPU 总使用率的百分比 NAME STATE CPU sec CPU MEM k MEM MAXMEM k MAXMEM VCPUS NETS NETTX k NETRX k VBDS VB
  • 日期时间差异返回正确的月份甚至年份?

    是否有任何内置函数如何以比仅天数更好的方式获取 DateTime 对象之间的差异 我的意思是 1 个月零 23 天 我发现由于每个月的天数 闰年等不同 计算起来非常困难 谢谢 看一下野田时间 http noda time googlecod
  • “Typemock Isolator”如何模拟静态方法?

    正如你们中的一些人所知 通常不可能在 net 中模拟静态方法 通过模拟 我的意思是用具有相同签名的另一个方法替换类中的方法 通常用于测试目的 用于模拟方法的两种主要方法是将其声明为虚拟方法或在接口中定义它 net 静态方法不允许使用这两种方
  • Chrome“无法拖动”图标会干扰鼠标悬停事件,我该如何防止这种情况?

    下面是一些使用 JavaScript 创建一堆 div 元素来充当像素的代码 我为 mouseover 事件添加了一个事件侦听器 并检查鼠标是否被按下 如果按下鼠标 我会更改该像素的颜色 最终结果是一个简单的绘图函数 我相信使用 HTML5
  • Entity Framework Core:获取所有表的列表

    如何获取数据库上下文中 Entity Framework Core 中所有表的列表 以下答案适用于 Entity Framework 5 中的早期版本 我们目前使用的是 EF Core 3 如何获取 EF 5 中所有实体的列表 https
  • 在 Propel 1.5 中执行多个条件的连接

    这个问题是从问题而来的here https stackoverflow com questions 6877226 rewriting not in sub select as join for propel and here https
  • 带有复杂编辑器的 JTable

    我有许多用于 JTable 的自定义编辑器 可以轻描淡写地说 其可用性 尤其是在使用键盘进行编辑方面 缺乏可用性 主要原因是我的编辑器总是在与此类似 尽管通常更复杂 的情况下创建 Override public Component getT
  • 从 SELECT 插入但更改一列?

    想知道是否有一种方法可以将行从另一个表插入到另一个表中 但一列除外 对于有限数量的列来说 这当然很容易 但是当列数增加时 列出所有列会有点烦人 我在想一些事情 Insert into table select replace col1 wi
  • Autofac。如何使用自定义方法(属性)来解析某些接口?

    我有以下接口 public interface IConfigurationProvider
  • Opera 跨源资源共享

    有人找到了 Opera 关于跨源资源共享的解决方法吗 我想做一个跨域XmlHttpRequest从我放置在 bar com 上的脚本到我的域 foo com The standard http www w3 org TR cors 目前为止
  • 跨文件的代码组织必须处理模板函数和内联

    我正在维护一个大型模板类库 它们基于以下任意一个执行代数计算float or double类型 许多类都有访问器方法 getter 和 setter 和其他运行少量代码的函数 因此当编译器找到它们的定义时 需要将这些函数限定为内联 相比之下