为什么有些事情在C++中留下了未定义的行为?如果其中一些在标准中预定义不是更好吗?
Why some things left undefined behavior in C++? Wouldn't it be better if some of them pre-defined in the standard?
我是C++程序员。在冲浪期间,我熟悉了未定义的行为、未指定的行为、实现定义的行为等术语。我想知道为什么有些事情没有定义?我知道C++接近硬件,但真的很难为其中一些定义行为吗?如果是这样,他们为什么不这样做?这个问题是关于为编译器实现保留如此多的行为背后的哲学。我认为并相信这样做有以下两个优点:
1)它允许更好的性能。它简化了编译器的工作,使得在某些情况下生成非常有效的代码成为可能。
2)它允许编译器供应商灵活地在自己的环境中实现它 道路。
如果您知道性能以外的任何其他因素,请告诉我。您的帮助将不胜感激。
谢谢
除了您已经提到的原因之外,一件重要的事情是了解 CPU 的不同。他们仍然这样做,但过去更糟。试图准确指定C++在极端情况下的行为方式是没有帮助的。例如 0/0
将由不同的CPU以不同的方式处理,这对于实际程序来说并不重要。
另一个问题是 某些UB很难检测到 。例如,跨翻译单元违反一个定义规则需要在链接器阶段提供支持,并且对依赖原始链接器的供应商有相当多的容忍度。
理念不会强迫你做出选择。如果某些东西受到架构的限制,那么就会有限制,但除此之外,很少有关于语义的任意决定,可以有多种解释。
如果您查看一些未定义行为的情况 - 空指针引用、浮点溢出等。计算机和操作系统的实际行为或多或少是未定义的。您无法假设在发生内存错误时,硬件是否会捕获或特定于操作系统的运行时是否能够以有效方式运行。
我们碰巧主要使用基于 x86 的机器,具有保护模式操作系统,这些操作系统都以合理的程度遵循 POSIX。但这并不总是正确的。
存在一些架构,其中仅初始化指向无效地址的指针会导致硬件陷阱 - 您甚至不必取消引用它。
存在未定义行为的大多数情况是因为它未定义,如 1/0
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- 如果要求比较器是严格的总排序,而不仅仅是严格的弱排序,C++标准算法会更快吗?
- 如果有标准::屏障,为什么是 std::闩锁?
- 如果可能,标准::映射分配是否静态
- 如果其他人在等待,是否有标准的STL或QT方法可以产生互惠码,否则请保留它
- 如何将 Boost 库与 CMake 链接(如果 boost 位于非标准位置,则在集群上)?
- 新标准中对memcpy生命周期初始化规则有哪些更改(如果有的话)
- 如果malloc/free对显然做了同样的工作,为什么C++标准库容器使用内存池
- 如果您属于"we don't use exceptions"阵营,那么您如何使用标准库?
- 如果包含标准容器,我可以标记MOVE-OPERATION NOEXCEPT
- 积极使用的C++环境缺乏对标准库的支持(如果不是全部的话,也是大多数)
- 为什么有些事情在C++中留下了未定义的行为?如果其中一些在标准中预定义不是更好吗?
- 什么是 ABI,为什么C++没有标准,如果有的话又有什么关系?
- 如果新的大小与旧的大小相同,标准是否保证std::string::resize不会起任何作用
- 如果我得了标准::bad_alloc该怎么办
- 值初始化是 C++98 标准的一部分吗?如果不是,为什么在 C++03 标准中添加它
- 如果标准容器元素类型和std::分配器类型不同,这是错误的吗
- 在一个简单的c++ 11四线程程序中,如果我注释标准输出打印行,我的两个消费者线程就不会返回
- 对于哪个标准容器(如果有的话),end()返回的迭代器是持久化的
- 如果标准保证使用初始值设定项,constexpr 是否? 'constexpr(constexpr auto x = f(); x) { }'