【问题标题】:Is an implementation allowed to site two identical function definitions at the same address, or not? [duplicate]是否允许实现将两个相同的函数定义放置在同一地址,或者不允许? [复制]
【发布时间】:2012-12-20 17:58:49
【问题描述】:

C++ 标准对等式运算符== 有如下说明:

[C++11: 5.10/1]: [..] 两个相同类型的指针比较相等当且仅当它们都为空,都指向同一个函数,或者都代表同一个地址。 p>

我最初的解释是,在这个级别上,函数本身在语义上没有“地址”,因此“或两者都表示相同的地址”只能指代对象,而不是函数。否则何必纠结于“指向同一个函数”子句呢?

也就是说,两个相同类型的函数指针比较相等当且仅当它们都指向同一个函数,句号。

这样做的结果是this question 中的行为(指向两个不同但相同的函数的指针具有相同的值)将是一个实现错误,因为指向不同函数的指针需要是唯一的。

感觉这是该子句的意图,但我无法客观地捍卫这样一种观点,即这应该是实际推断段落含义的方式,或者它确实是委员会的意图,现在是我的解释has come into question

[D] 与我讨论“[...] 或两者如何代表同一个地址。”对 Visual C++ 的行为不满意。 (@jstine)

所以我的问题是关于这个标准段落的意图。

要么:

  • 我在正确的轨道上:函数指针必须比较相等iff它们都指向同一个函数(“地址”该死),或者

  • 文中存在冗余:函数指针必须比较相等iff它们都指向同一个函数或都代表同一个地址;并且,通过扩展,允许实现使两个函数存在于同一地址。

这是什么?

【问题讨论】:

  • 这是一个棘手的问题=P
  • @alex:谢谢,但我的意思是iff
  • 此要求将有效地强制模板膨胀。
  • 不在乎。语言律师可以对此进行辩论,但实际上我认为它不会影响实际程序。
  • @brian:affected Mehrdad's 已经够好了。

标签: c++ language-lawyer


【解决方案1】:

好吧,从逻辑上看这个语句。你有三个子句:

  1. 两者均为空。

  2. 两者都指向同一个函数。

  3. 两者的地址相同。

这些子句由逻辑“或”连接。因此,如果其中任何一个为真,则允许两个指针比较相等。如果编译器如此决定,则可能会失败 #3 但仍会通过 #2。逻辑“或”表示这样的指针比较相等。

另外,需要注意的是,成员指针没有传统意义上的“地址”。它们确实有一个值,但它不是内存地址。这就是为什么你不能将它们投射到void* 等等。

该段落保证,给定函数指针tu,如果t == ut(...); 将导致与u(...); 相同的行为。该行为将引用 NULL、调用相同的函数或在相同地址执行代码。因此,具有相同的行为。

从技术上讲,Mehrdad's problem 是他从两个不同的成员函数名称中获取相同的值。所以#3 适用。我没有看到标准中要求不同的成员函数名称在为它们获取函数时返回不同的值。

【讨论】:

  • 我有点困惑:它怎么会失败#3(它们指向不同的地址)并通过#2(它们指向相同的 fxn)?如果我将它们都转换为 void*,它们将具有不同的值并且比较不同,而在转换为 void* 之前它们比较相等。这可能吗?
  • @AndyProwl:规范中没有规定两个指针相等在转换为 void* 后将相等。也不是说两个不相等的指针在这样的转换之后就不相等了。
  • 但如果我在两行之间正确阅读,它要求从 void* 转换回原始类型会产生原始值。但是相同的 void* 值无法转换为相同原始类型的两个不同值
  • (我指的是 5.2.9/13 和 5.2.10/8)- 只是想了解一下。所有这些听起来都让我感到困惑。我只是希望不同的函数有不同的地址只要程序似乎关心
  • #3 发生但#2 没有发生很容易是专门化优化的结果,其中相同的逻辑函数被编译为两个不同的实现,这两个实现取决于调用站点的不同静态保证,在这种情况下,编译器可以在某处记录额外数据,以确保函数指针在具有不同地址的情况下仍然比较相等(例如,指针可能包含多个地址,或者可能使用一些额外的表)。我不知道是否有任何主流编译器在实践中这样做,但没有理由禁止它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多