繁体   English   中英

在try / catch块中新建(std :: nothrow)与New

[英]New (std::nothrow) vs. New within a try/catch block

在学习new之后我做了一些研究,不像我习惯的malloc() ,对于失败的分配没有返回NULL,并且发现有两种不同的方法来检查new是否成功。 这两种方式是:

try
{
    ptr = new int[1024];
}
catch(std::bad_alloc& exc)
{
    assert();
};

ptr = new (std::nothrow) int[1024];
if(ptr == NULL) 
    assert();

我相信这两种方式可以实现相同的目标,(如果我当然错了,请纠正我!),所以我的问题是:

这是完全基于可读性,可维护性和性能来检查new成功的更好选择,同时忽略了事实上的c ++编程约定。

考虑一下你在做什么。 你正在分配内存。 如果由于某种原因,内存分配无法工作,那么assert 如果你只是让std::bad_alloc传播回main那么或多或少会发生什么。 在发布版本中, assert是no-op,当程序尝试访问内存时,程序将崩溃。 所以它就像让异常泡沫化一样:暂停应用程序。

所以问问自己一个问题:你是否真的需要关心如果内存不足会发生什么? 如果你所做的只是断言,那么异常方法更好,因为它不会使用随机assert你的代码混乱。 你只是让异常回归main

如果你确实在你无法分配内存的情况下有一个特殊的代码路径(也就是说,你实际上可以继续运行),异常可能会或可能不是一种可行的方式,具体取决于代码路径。 如果代码路径只是一个指针为空的开关集,那么nothrow版本将更简单。 相反,你需要做一些相当不同的事情(从静态缓冲区中取出,或者删除一些东西,或者其他东西),然后捕获std::bad_alloc非常好。

这取决于分配发生的背景。 如果您的程序即使分配失败也可以继续(可能会向调用者返回错误代码),然后使用std::nothrow方法并检查NULL。 否则你将使用控制流的异常,这不是一个好习惯。

另一方面,如果您的程序绝对需要成功分配内存以便能够运行,请使用try-catch来捕获(不一定在new附近)异常并从程序中优雅地退出。

从纯粹的性能角度来看,它很重要。 异常处理存在固有的开销,尽管这种开销通常值得在应用程序可读性和维护方面进行权衡。 这种性质的内存分配失败不应该在您的应用程序的99%情况下,因此这种情况很少发生。

从性能角度来看,您通常希望避免使用标准分配器,因为它的性能相对较差。

所有这些说,我通常接受异常抛出版本,因为通常我们的应用程序处于这样一种状态,即如果内存分配失败,我们除了使用适当的错误消息正常退出之外我们几乎无能为力,并且我们通过不要求NULL检查来节省性能在我们新分配的资源上,因为根据定义,分配失败会将范围从重要的地方移出。

new用于创建对象,而不是分配内存,因此您的示例有点人为。

如果失败,对象构造函数通常会抛出。 在Visual Studio中多次执行new实现后,我不相信代码会捕获任何异常。 因此,在创建对象时查找异常通常是有意义的。

认为仅当内存分配部分失败时才会抛出std::bad_alloc 我不确定如果你将std::nothrow传递给new但是对象构造函数抛出会发生什么 - 我读过的文档中存在歧义。

两种方法之间的性能差异可能无关紧要,因为大多数处理器时间可能很容易在对象构造函数中使用或搜索堆。

经验法则并不总是合适的。 例如,实时系统通常会限制动态内存分配,因此new (如果存在)可能会过载。 在这种情况下,它可能会使用返回的空指针并在本地处理失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM