这是因为函数表和重载函数在 C++ 中的工作方式。
当编译器读取你的std::string some_function();
文件时,它会创建一个点供它在二进制文件中引用,并说是否“这个函数被调用过跳转到这个点”。
所以我们有一个看起来像这样的vtable......
(Address offset) (Symbol)
0x???????? std::string somefunction();
现在它到达你的auto some_function() {...}
. 通常它会首先在函数表中查看是否auto somefunction();
存在于表中或表中是否存在一些变体,但编译器注意到这是一个实现并且它具有 auto 关键字以便减少它写入*blank* some_function();
函数表的熵和关系解决返回类型。
现在函数表看起来像这样......
(Address offset) (Symbol)
0x???????? std::string somefunction();
0x???????? ????? somefunction();
因此,当它发现返回类型(在本例中为std::string
. 编译器现在知道返回类型是什么,因此它会转到函数表并进行auto somefunction();
更改std::string somefunction();
。
现在函数表看起来像这样......
(Address offset) (Symbol)
0x???????? std::string somefunction();
0x???????? std::string somefunction();
现在编译器返回并继续编译函数。完成后,它会返回并完成 vtable 只是发现相同的符号在那里两次。现在我们所指的符号也很模糊。
那么这是什么原因呢?
不是 100% 确定,但 vtables 是在您的代码被处理到足以允许进行扣除类型之前很久就制作的。因此,编译器在那个阶段必须使用的唯一选择就是假设它是一个新符号。这只是我注意到整天查看符号表并编写我自己的 C++11 编译器的东西。
但是,我不能代表其他引入了许多优化和其他步骤的编译器,我只是简单地工作,但这是我对标准的理解。
最后一件事,类型是完全任意的。即使他们在扣除时不匹配也没关系。它永远不会那么远。问题出现在表中有两个相同的符号,并且您不能重载返回类型。