假设以下源文件(翻译单位;TU):
struct X {
int i;
X(const X&);
X(X&&);
};
X::X(const X&) = default;
X::X(X&&) = default
如果我用 Clang 编译它,它会生成复制和移动构造函数的机器代码。但是,GCC 仅为移动构造函数生成它,并且生成的目标文件中缺少复制构造函数的机器代码。我首先以为这是与编译器资源管理器相关的问题,但后来我使用
objdump
在本地 Linux 系统上观察到了相同的行为。
现场演示:https://godbolt.org/z/1re4brr6P
我不明白这一点,因为一旦我有另一个具有复制构造函数调用的 TU,就需要从机器代码中调用它:https://godbolt.org/z/3YaMTd5do。因此,GCC 在第二个 TU 中生成复制构造函数的调用,但不在第一个 TU 中生成其机器代码。那么链接器如何将目标文件链接在一起?
这只是编译器资源管理器如何呈现输出的问题。
GCC 在同一地址为两个构造函数定义符号,因为这些函数具有完全相同的行为。符号表:
$ nm test.o
0000000000000000 T _ZN1XC1EOS_
0000000000000000 T _ZN1XC1ERKS_
0000000000000000 T _ZN1XC2EOS_
0000000000000000 T _ZN1XC2ERKS_
$ nm -C test.o
0000000000000000 T X::X(X&&)
0000000000000000 T X::X(X const&)
0000000000000000 T X::X(X&&)
0000000000000000 T X::X(X const&)
通常编译器无法优化两个函数以使其具有完全相同的地址,但对于构造函数来说这是可以的,因为在 C++ 中没有办法观察构造函数的地址。