不同的功能有不同的地址吗?

时间:2014-10-23 17:21:22

标签: c++ function-pointers language-lawyer one-definition-rule comdat-folding

考虑这两个功能:

void foo() {}
void bar() {}

是否保证&foo != &bar

类似地,

template<class T> void foo() { }

是否保证&foo<int> != &foo<double>


我知道折叠函数定义有两个连接符。

MSVC积极地COMDAT折叠函数,因此具有相同实现的两个函数可以转换为一个函数。作为副作用,这两个函数共享相同的地址。我的印象是这是非法的,但我无法找到标准中的哪些内容是非法的。

The Gold linker也会折叠功能,同时设置为safeallsafe表示如果采用功能地址,则不会折叠,而all即使采用地址也会折叠。因此,如果函数具有不同的地址,则gold的折叠safe表现为。

虽然折叠可能是意料之外的,并且存在依赖于具有不同地址的不同(相同实现)函数的代码(因此折叠可能是危险的),但在当前的C ++标准下它实际上是非法的吗? (此时为C ++ 14)(自然如果safe折叠是合法的)

3 个答案:

答案 0 :(得分:11)

是。从标准(§5.10/ 1):“两个相同的指针 类型比较等于当且仅当它们都为空时,两者都是点 相同的功能,或两者代表相同的地址“

实例化后,foo<int>foo<double>是两个不同的功能,因此上述内容也适用于它们。

答案 1 :(得分:7)

因此,有问题的部分显然是或两者都代表相同的地址(3.9.2)

IMO这部分显然是为了定义对象指针类型的语义。仅适用于对象指针类型。

短语引用第3.9.2节,这意味着我们应该看一下。 3.9.2关于对象指针所代表的地址的讨论(以及其他)。它没有谈论函数指针所代表的地址。其中,国际海事组织只留下两种可能的解释:

1)这个短语根本不适用于函数指针。这只剩下两个空指针和两个指向同一函数的指针,比较相等,这可能是我们大多数人所期望的。

2)这句话确实适用。由于它引用了3.9.2,它没有说明函数指针所代表的地址,我们可以使任何两个函数指针进行比较相等。这是非常意外的,当然渲染比较函数指针是完全没用的。

所以,虽然从技术上来说可以说明(2)是有效的解释,IMO它不是有意义的解释,因此应该被忽视。既然不是每个人似乎都同意这一点,我也认为需要对标准进行澄清。

答案 2 :(得分:3)

  

5.10平等运算符[expr.eq]

     

1 ==(等于)和!=(不等于)运算符组从左到右。操作数应具有算术,枚举,指针或指向成员类型的指针,或者键入std::nullptr_t。运算符==!=都会生成truefalse,即bool类型的结果。在下面的每种情况下,操作数在应用指定的转换后应具有相同的类型
  2 如果至少有一个操作数是指针,则在两个操作数上执行指针转换(4.10)和限定转换(4.4)以将它们带到它们的复合指针类型(第5节)。比较指针定义如下:两个指针比较相等,如果它们都是空的,都指向相同的函数,或者两者都代表相同的地址(3.9.2),否则它们比较不相等。

让我们采取最后一点比特:

  1. 两个空指针比较相等 对你的理智有好处。
  2. 同一功能的两个指针比较相等 其他任何事都会非常令人惊讶 这也意味着只有一个任何inline函数的外联版本可能会使用其地址,除非你想使函数指针比较过于复杂和昂贵。
  3. 两者代表相同的地址 现在,这就是它的全部内容。删除此内容并将if and only if简化为简单的if会让其解释,但明确授权使任何两个函数相同,只要它否则不会改变符合要求的程序的可观察行为。