主要区别在于使用异常处理的版本至少可以工作,而使用if
语句的版本可能无法工作。
你的第一个片段:
int *ptr = new int[1000];
if (ptr == NULL) {
// Handle error cases here...
}
...似乎假设new
在失败的情况下将返回一个空指针。虽然这曾经是真的,但已经很久没有了。对于任何当前合理的编译器,new
只有两种可能性:成功或抛出。因此,您的第二个版本与 C++ 的工作方式一致。
如果你真的想使用这种风格,你可以重写代码让它在失败的情况下返回一个空指针:
int *ptr = new(nothrow) int[1000];
if (ptr == NULL) {
// Handle error cases here...
}
在大多数情况下,new
无论如何你都不应该直接使用——你应该真正使用std::vector<int> p(1000);
并完成它。
有了这个,我觉得有必要为大量代码添加这一点,这可能是最有意义的,不做任何事情并简单地假设内存分配会成功。
曾经(MS-DOS)如果您尝试分配比可用内存更多的内存,内存分配实际上会失败是相当普遍的——但那是很久以前的事了。如今,事情并不那么简单(通常)。当前系统使用虚拟内存,这使情况变得更加复杂。
在 Linux 上,通常会发生的情况是即使内存并不真正可用,Linux 也会执行所谓的“过度提交”。你仍然会得到一个非空指针,就好像分配成功了一样——但是当你尝试使用内存时,就会发生不好的事情。具体来说,Linux 有一个所谓的“OOM Killer”,它基本上假设内存不足是错误的迹象,所以如果发生这种情况,它会尝试找到有错误的程序,并杀死它/它们。对于大多数实际目的,这意味着您的程序可能会被杀死,而其他(半任意选择的)程序也可能会被杀死。
Windows 更接近 C++ 所期望的模型,因此如果(例如)您的代码在无人值守的服务器上运行,则分配实际上可能会失败。然而,早在它失败之前,它就会把机器的其余部分拖到膝盖上,疯狂地交换,试图使分配成功,但注定失败。如果用户当时实际上正在操作机器,他们通常会杀死您的程序或杀死其他一些程序,以便为您的代码释放足够的内存以相当快地获得请求的内存。
在这些情况下,针对分配可能失败的假设进行编程并不是特别现实。对于大多数实际目的,会发生以下两种情况之一:分配成功或程序终止。
这又回到了之前的建议:在典型情况下,您通常应该只使用std::vector
,并假设您的分配会成功。如果您需要提供除此之外的可用性,则只需以其他方式执行此操作(例如,如果进程死亡,则重新启动进程,最好以使用较少内存的方式)。