由于未定义的行为,许多不好的事情发生并且继续发生(或者不知道,谁知道,任何事情都可能发生).据我所知,这是为了让编译器进行优化留下一些摆动空间,也可能使C++更容易移植到不同的平台和架构.然而,由未定义的行为引起的问题似乎太大而无法通过这些论证来证明.未定义行为的其他参数是什么?如果没有,为什么还存在未定义的行为?
编辑为我的问题添加一些动机:由于使用较少C++的几个糟糕经历 - 狡猾的同事,我已经习惯了使我的代码尽可能安全.断言每一个论点,严谨的正确性以及类似的东西.我试图离开,因为小房间可能以错误的方式使用我的代码,因为经验表明,如果有漏洞,人们会使用它们,然后他们会打电话给我,说我的代码很糟糕.我认为让我的代码尽可能安全是一种好的做法.这就是为什么我不明白为什么存在未定义的行为.有人可以给我一个未定义行为的例子,这些行为在运行时或编译时无法检测到而没有相当大的开销吗?
我试图理解下面的代码res1之间的区别:res2
#include <iostream>
int main()
{
int x = 1;
int y = 0;
double res1 = double(x)/y; // OK: evaluates to Inf
int res2 = x/y; // run-time error: Floating point exception
// 1/0; // g++ warning: division by zero [-Wdivision-by-zero]
std::cout << res1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
据我了解,除以零是 C++ 标准中未定义的行为,并且res1和之间存在差异的原因res2是由于我的机器为 实现了 IEEE 754 double,它需要除以零才能返回Inf或-Inf。
但现在我想知道为什么标准必须首先对除以零做出任何声明。这个答案说它是为了适应实现 C++ 的各种不同的体系结构,但我不确定 -除以零不是更多的运行时问题吗?特别是如果编译器在大多数情况下不太可能在不评估分母的情况下检测到它(我认为这就是上面示例中发生的情况)。当然,如果我尝试类似 的操作 …
我最近一直在努力学习C.来自Java,它让我感到惊讶,你可以执行声明为"未定义"的某些操作.
这对我来说似乎非常不安全.我理解程序员不负责执行未定义的操作,但为什么它甚至可以从一开始就被允许?例如,为什么编译器不能捕获超出范围的数组索引,甚至悬挂指针?你最终只能访问你永远不应该访问的内存块,没有明显的理由.
作为比较,Java 更加确定你不会做任何愚蠢的事情,像热饼一样抛出异常.
当然,必须有一个理由允许这样做吗?它是什么?
答案:据我了解,主要原因是表现.此外,Java确实有未定义的行为,尽管没有这样标记.
编辑:限制问题到C
C++ 不定义某些行为(例如更好的错误检查)的原因是什么?为什么不抛出一些错误并停止呢?
一些伪代码例如:
if (p == NULL && op == deref){
return "Invalid operation"
}
Run Code Online (Sandbox Code Playgroud)
对于整数溢出:
if(size > capacity){
return "Overflow"
}
Run Code Online (Sandbox Code Playgroud)
我知道这些都是非常简单的例子。但我很确定大多数 UB 都能被编译器捕获。那么为什么不实施它们呢?因为它确实很耗时并且不进行错误检查更快?一些 UB 可以通过单个 if 语句捕获。那么也许速度并不是唯一的问题?