任何人都有关于编译器删除全局和静态符号的C ++标准所说的链接?我认为如果没有引用全局符号,编译器将无法保证删除全局符号。我的一位同事声称,如果您的全局符号包含在主翻译单元中,那么这些符号即使未被引用也不会被删除。
答案 0 :(得分:3)
有趣的是,我在C ++ 2003标准中可以找到的就是:
3.7.1静态存储持续时间[basic.stc.static]
所有既没有动态的物体 储存时间也不是当地的 静态存储时间。存储 因为这些物体应该持久 计划的持续时间(3.6.2, 3.6.3)。
如果是静态存储的对象 持续时间有初始化或 具有副作用的破坏者,它应该 即使它出现也不被淘汰 不使用,除了一个班级 对象或其副本可能被删除 如...中所述 12.8。
这意味着标准允许在静态存储中删除项目,如果它们的初始化和破坏没有副作用,否则它们将被闲置。
如果有更直接的许可,我没有看到它(但也许其他人会这样做)。
但是,应该注意的是,让链接器消除最终图像中未使用的对象是一种非常常见的优化。
答案 1 :(得分:0)
你问了一个关于链接的问题,尽管C ++标准认为链接应该作为翻译的最后阶段发生,但它没有说明应该如何发生。例如,它表示函数引用已被解析,但它不要求它们按名称解析,也没有说明解析后引用会发生什么。
要确定编译器在目标代码中包含哪些符号,以及链接器执行或不删除哪些符号,您需要分别查阅您正在使用的编译器和链接器的文档。< / p>
答案 2 :(得分:0)
这是我相信的方式(我们之前在评论主题中对堆栈溢出进行了长时间的讨论):
在任何情况下,编译器必须在使用完成之前初始化对象,但不一定在main之前。我做了测试,因为stackoverflow上的某个人说如果没有这样的用途,gcc会有效地优化具有副作用的对象的初始化。我现在测试了,我看到gcc没有这样做。另外,据我了解标准,无论如何都不允许这样做。
如果您只是获取要初始化的对象的翻译单元的对象或函数的地址就足够了。为了安全起见,最好总是这样做,即使对于具有副作用的初始化的对象也是如此。假设你的朋友是对的,我认为对于main的翻译单元,main
总是被视为使用,因此立即满足条件。规则可以在3.6.2p3
,3.7.1p2
和3.2p2
(使用的定义),1.9p7
中找到(副作用的定义< / em>的)。