gpt4 book ai didi

c++ - 从标准库中重新定义一个函数是否违反了一个定义规则?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:22:07 25 4
gpt4 key购买 nike

#include <cmath>

double log(double) {return 1.0;}
int main() {
log(1.0);
}

假设函数log()<cmath>在全局命名空间中声明(这实际上是未指定的,我们只是做这个假设),然后它引用与 log() 相同的函数我们定义的函数。
那么这段代码是否违反了单一定义规则(参见 here ,由于不需要诊断,这段代码可能会在某些编译器中编译,我们无法断言它是否正确)?

注意:经过最近的编辑,这不是以下的拷贝:What exactly is One Definition Rule in C++?

最佳答案

典型场景。

如果extern "C" double log(double)最初是在全局命名空间中声明的,然后您重新声明了它并提供了定义。该实现先前提到的 extern "C"延续到您的匹配重新声明。您的定义适用于属于实现的功能,并且违反了 ODR。

关于UB的表现:治疗显然很常见log作为弱链接符号。您的实现会覆盖 libc.so根据 ABI 规则。

(如果实现不做 extern "C" ,基本上还是一样。)

其他可能的情况。

如果lognamespace std 中声明然后带入全局命名空间,那么你的声明就会和它冲突。 (实际上,using 声明在技术上是一个声明。)诊断出此错误。

违反假设的场景。

then it refers to the same function as the log function we defined

实现方式之一是 <cmath>名称进入全局命名空间将声明 extern "C"内部功能 namespace std , 然后做 using namespace std ,并确保在包含任何标准 header 时始终将其作为第一件事发生。自 using namespace不是“粘性的”——它只适用于指定命名空间中的前面声明——标准库的其余部分将不可见。 (这不会声明全局命名空间中的名称,但标准只说“放置在全局命名空间范围内。”)

在这样的实现中,您的声明将隐藏标准声明并声明一个新函数,该函数具有新的损坏名称(例如 _Z3logd 而不是简单的 log )和新的完全限定名称( ::log 而不是::std::log)。这样就不会有 ODR 违规(除非某些内联函数在一个 TU 中使用一个 log 而在另一个 TU 中使用另一个)。

关于c++ - 从标准库中重新定义一个函数是否违反了一个定义规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41670800/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com