我是现有公司的新成员,并且正在处理由我的直接团队负责人撰写的项目。该公司通常不使用C ++,但我的同事用C / C ++编写了高效的代码。我们只知道如何用C ++编写代码(我和我的领导,所以没有第三种意见可以参与)。
在我对项目有足够深入了解后,我意识到整个结构是...... 特殊。
它实际上由一个编译单元组成,其中makefile仅列出main.hpp
的源。
然后,此头文件包含项目所包含的所有源文件,因此它看起来像一个非常大的列表:
#include "foo.cpp"
#include "bar.cpp"
在尝试理解它背后的逻辑时,我意识到这确实适用于这个项目,因为它只是一个接口,每个单元可以在不访问任何其他单元的情况下运行,在某些时候我问他是什么是他这样做的原因。
我对这个论点采取了防御性的反应
嗯,这是有效的,不是吗?如果您认为对您更好,您可以自由地按照自己的方式行事。
这就是我现在所做的,仅仅是因为我在思考这个结构时遇到了麻烦。所以现在我应用"通常"我现在正在编写实现的结构,同时只对整个项目进行强制性更改,以演示我将如何设计它。
我认为存在许多缺点,从混合链接器和编译器开始,通过自己的项目结构工作不能很好地服务,直到优化可能会以冗余或模糊的结果结束,更不用说干净了该项目的建设需要约30分钟,我认为可能也是由结构引起的。但是,我缺乏知名度,而不仅仅是假设的问题。
作为他的论点"它是我的方式,不是吗?"是的,我希望能够向他解释为什么反正这不是一个坏主意,而不是作为新的挑剔家伙过来。
那么这样的项目结构究竟会导致什么问题呢? 或者我反应过度,这样的结构完全没问题?
答案 0 :(得分:5)
更不用说项目的(干净)构建需要大约30分钟
主要缺点是对代码的任何部分进行更改都需要从头开始重新编译整个程序。如果编译需要一分钟,这可能不会很重要,但如果需要30分钟,那将会很痛苦;它会破坏make更改 - >编译 - >测试工作流程。
更不用说项目的干净构建需要大约30分钟
具有单独的翻译单元实际上从头开始编译通常要慢得多,但是您只需要在更改时单独重新编译每个单元,这是主要优点。当然,通过在所有翻译单元中包含大量的,经常变化的标题,很容易错误地破坏这种优势。单独的翻译单位需要小心谨慎才能做到。
现在,对于多核CPU,多个翻译单元允许的并行性可以缓解从头开始的较慢构建(如果单个翻译单元的大小恰好达到最佳点,可能甚至可以克服这个缺点,并且足够的核心;你需要一些彻底的研究才能找到答案。)
另一个潜在的缺点是整个编译过程必须适合内存。当内存变得超过开发人员工作站上的可用内存时,这只是一个问题。
总之:问题在于,一个大规模的源文件方法无法很好地扩展到大型项目。
现在,谈谈优势,公平
直到优化可能会以冗余或模糊的结果结束
实际上,单个翻译单元比单独翻译单元更容易优化。这是因为某些优化,特别是内联扩展,不可能跨翻译单元,因为它们依赖于当前编译的翻译单元中没有的定义。
由于链接时间优化已在流行编译器的稳定版本中提供,因此优化优势已得到缓解。只要您能够并且愿意使用现代编译器,并启用链接时间优化(默认情况下可能未启用)
PS。将单个来源文件命名为扩展名.hpp
非常不常见。
答案 1 :(得分:2)
首先我要提到的是单个编译单元项目的优点:
n
翻译单元的常规项目,编译时间将随着每个新翻译单元的增加而线性增长。使用SCU时,它将以对数方式增长,并且在大型项目中添加新单元几乎不会影响编译时间。 现在有缺点:
#include
指令的一致排序,强制包含当前文件直接需要的标头,正确的转发,一致的命名约定等。问题是没有工具可以帮助开发人员解决此问题甚至是标题中的轻微违规组织可能会导致构建日志混乱。P.S。