"no diagnostic required"的理由是什么?
What is the rationale to "no diagnostic required"?
大多数人都熟悉c++中的"undefined"answers"unspecified"行为注释,那么"no diagnostic required"呢?
我注意到这个问题和答案,处理格式不良的程序,但没有详细说明"不需要诊断"语句的根源。
委员会在将某物分类为"不需要诊断"时采用的一般方法是什么?
- 标准委员会需要多严重的错误来指定它?
- 这些错误的性质是否几乎不可能检测到,因此无法诊断?
"未定义"answers"未指定"行为的例子比比皆是;除了ODR之外,还有哪些"不需要诊断"类型错误的实际示例?
这里有一个讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/lk1qavcivility与各委员会成员的话语。
普遍的共识似乎是
- 无规范性差异
- 不规范的;仅用于编译时规则违规,从不用于运行时规则违规。
正如我在那篇文章中所说的,我确实在一次讨论中听到过(我记不清是哪一次了,但我肯定有有见地的委员会成员参与其中)
- 不规范的;对于明显违反规则的情况,不需要诊断,原则上可以在编译时诊断,但需要实现付出巨大的努力。
- 未定义的行为用于实现可以找到有用意义的事情,因此不一定是纯粹的邪恶,以及任何导致任意后果的运行时违规。
我的粗略指南是;如果它是在编译时,它往往是"病态的;如果是在运行时,它总是"未定义行为"。
对于归类为未定义行为(UB)的行为,我会尝试解释"无需诊断"。
标准说"UB不需要诊断"1,给编译器完全的自由来优化代码,因为编译器只能通过假设你的程序是完全定义良好的(这意味着你的程序没有UBs)来消除许多开销,这是一个好的假设—毕竟,如果这个假设是错误的,那么编译器基于这个(错误的)假设所做的任何事情都将以一种未定义的(即不可预测的)方式表现,这是完全一致的,因为你的程序无论如何都有未定义的行为!
请注意,包含UBs的程序具有像任何东西一样的行为自由。再次注意,我说"一致"是因为它与标准的立场是一致的:"语言规范和编译器都不能保证你的程序的行为,如果它包含UB"。
<一口> 1。与之相反的是"诊断要求",这意味着编译器被要求通过发出警告或错误消息向程序员提供诊断。换句话说,不允许假定程序定义良好,从而优化代码的某些部分。一口>
这里有一篇文章(在LLVM博客上)用例子进一步解释了这一点:
- C语言中未定义行为的优点,附示例(第一部分)
文章的例外(斜体mine):
有符号整型溢出:如果对'int'类型进行算术处理(例如)溢出,结果未定义。例如,"INT_MAX+1"是不能保证是INT_MIN。的某些类对某些代码来说很重要的优化。例如,知道INT_MAX+1未定义允许将"X+1> X"优化为"true"。知道乘法"不能"溢出(因为这样做会未定义)允许将"X*2/2"优化为"X"。虽然这些看起来微不足道,这类事情通常通过内联和宏扩展。这允许的更重要的优化是"<="像这样循环:
for (i = 0; i <= N; ++i) { ... }
在此循环中,编译器可以假定循环将进行迭代如果"i"在溢出时未定义,则恰好是N+1倍,这允许a广泛的循环优化启动。另一方面,如果变量被定义为在溢出时绕行,然后是编译器必须假设循环可能是无限的(如果N是INT_MAX)——然后禁用这些重要的循环优化。这尤其会影响64位平台,因为有太多的代码使用"int"作为归纳变量
值得注意的是,保证定义了无符号溢出因为2的补码(换行)溢出,所以你总是可以使用它们。的定义有符号整数溢出的代价是优化只是失去了(例如,一个常见的症状是吨在64位目标上的循环内的符号扩展)。Clang和GCC接受"-fwrapv"标志,该标志强制编译器处理定义的有符号整数溢出(除了INT_MIN除以1) .
我建议你阅读整篇文章—它有三个部分,都很好。
- 第二部分
- 第三部分
希望对你有帮助。
- 有什么理由C++ 11+ std::mutex 应该声明为全局变量,而不是作为函数参数传递到 std::thread 中
- 不允许功能模板的部分专业化背后的理由是什么?
- 这个错误是什么?似乎没有理由出现
- typeid 运算符忽略 cv 限定符背后的理由是什么?
- 对于类型是类模板专业化的参数,ADL背后的理由是什么
- 有什么理由更喜欢从 IDE 中运行应用程序而不是运行独立的可执行文件?
- 有什么理由为什么“std::exchange”不是“constexpr”
- 当编译器看到 std::vector<Typo> 和 std::vector<struct 拼写错误时发出的诊断之间的差异背后的理由是什么>
- 有什么理由在 C++17 中使用 std::map::emplace() 而不是 try_emplace() 吗?
- "inline function need to be DEFINED in all tranlation units"背后的理由是什么?
- 延长临时工的使用寿命的理由是什么
- 允许“?”被转义的理由是什么?
- 保留 std::initializer_list 的副本是否安全?理由是什么
- "no diagnostic required"的理由是什么?
- 将所有引用形参设为const的理由是什么?
- 将monotonic_clock重命名为 steady_clock 的理由是什么<chrono>?
- 这种未定义行为的理由是什么
- 有什么理由使用(MFC)CList<T,T&>而不是CList<T,const T&>?
- 不允许绑定到初始化列表中的引用的临时存在于actor结束之后的理由是什么?
- 声明指向*this*对象的指针的优点或理由是什么?