如何找出编译器生成的函数?

14

我知道编译器生成的函数、三法则和五法则。在现实世界的场景中,确定编译器实际上创建了哪些编译器生成的函数(构造函数、赋值运算符、析构函数)可能并不容易。

有没有办法列出特定类的编译器生成的函数?

我主要关注Visual Studio 2019和Xcode,但是通用的解决方案更加受欢迎。

3个回答

15
规则很复杂。我将从另一个答案中引用一张表,该答案引用了Howard Hinnant的演示文稿

enter image description here

这里的道德是一个好的实践是不要依赖编译器的隐式声明,而是显式声明每个特殊成员(根据您的需求进行默认或删除)。

如果您明确声明了每个特殊成员,那么您将失去移动构造函数和赋值运算符的“未声明”特殊成员状态。 - Maxim Egorushkin
2
@bolov 这个图表很有用,但它并没有回答我的问题。我想找出哪些函数实际上是由编译器生成的。换句话说:我不是在问理论上应该发生什么,而是在问实际上正在发生什么。 - Helge Klein
删除的成员会触发编译器错误,而“未声明”的成员则不会。这迫使您手动实现该成员,而不是写“= default”。 “未声明”与默认和已删除不同,您可能需要重新观看您引用图片的讲话。 - Maxim Egorushkin
1
@tjwrona1992:按照这个论点,我们永远不需要测试我们的代码,因为我们会知道如果编译器做了与我们意图不同的事情,那么它一定存在漏洞。 - ruakh
1
@tjwrona1992:是的,完全正确。同样,查看编译器生成的内容的目的不是验证编译器是否正确,而是验证您是否向编译器提供了正确的输入。 - ruakh
显示剩余8条评论

7
有没有办法列出特定类的编译器生成函数?在Linux(和其他Unix系统)上,您可以使用nm、readelf和objdump对生成的目标文件/库/可执行文件进行反汇编并检查导出的符号(以及更多内容)。在Windows上有类似的工具,但我不怎么使用这个平台,所以无法提供具体的工具名称。

1
尽管这些工具可能无法显示哪些函数可能已生成(即,编译器被允许生成它们,但您从未使用过这些函数,因此它决定不费心,或链接时代码消除将其摆脱)。 - JMAA
1
严格来说,这个答案更精确地回答了所提出的问题:“编译器生成了哪些方法?”这与“在不同的上下文中编译器可能生成了哪些方法”这个不太精确的问题是不同的。 - rici
1
@jesper:不,我已经点赞了。正如我所说的那样,我认为你回答的问题更加精确。另一个问题可能是有意而为之的,因为它是反事实的:我们不知道它可能包含哪些假设情境。但这就是字面上提出的问题,无论是否有意,你都很好地回答了它。 - rici
@ric:这是直接来自于这个答案:“你可以在生成的目标文件/库/可执行文件上使用nm、readelf和objdump”。 - IInspectable
@IInspectable:没错。生成的目标文件就是编译器产生的。目标文件是链接器的输入,链接器会生成可执行文件。因此,你也可以将这些工具用于链接器的输出,但你可以专门将它们用于编译器的输出。(或者用于将多个目标文件组合成库的归档器的输出。) - rici
显示剩余8条评论

1
这目前只是一个部分回答。

Visual Studio 2019

构造函数

在定义类对象时,Visual Studio的智能感知功能会显示可用的构造函数,包括编译器生成的和你自己定义的:

enter image description here

很不幸,这些信息并不总是自动显示。为了让上面的截图正常工作,我不得不在括号内输入一些内容,因此出现了逗号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接