寻找一个没有异常数组的好解决方案

时间:2015-08-31 21:19:33

标签: c++ arrays exception

如果我没弄错,std :: array / vector都会抛出异常。 有可能消除这种情况吗? 例如,我知道我可以将nothrow添加到new,这样它就不会抛出异常,只返回null。

我需要使用某种类型的数组,我更喜欢一些std版本而不仅仅是new []版本,但不希望涉及到异常。 你能推荐一个好的选择吗?

1 个答案:

答案 0 :(得分:2)

技术上,不是雪人在删除的答案的评论中提出的超出“不可能”的原始问题的答案。但是我希望我能就解决方案提供一些建议,以及“无例外”政策背后的哲学和思想,可以用来争论使用std::vector作为一件好事,而不是要避免的事情。显然,由读者决定这样的论证是否可能导致读者作为个人和项目的积极或不积极的结果。

编码标准中“无异常”规则的目的通常是避免相当混乱的情况,其中存在大量不同的异常,在不同级别处理,并且代码变得难以阅读 - 它可以是难以管理,并且是“绝不能抛出异常”的合理理由。

如果这是目的(而不是例如“我们使用的是不支持异常的编译器,因为它是唯一一个支持我们需要编译的处理器X”),那么我会争辩说仍然应该允许使用std::vectorstd::map,也许在try ... catch内部main [或类似的中心位置]捕获所有异常,并在合理的用户中报告异常友好的方式,然后退出 - 因为你的代码不会“正确”如果你遇到std::vector抛出排除的情况 - 它不是“正常操作”的一部分内存不足或访问超出范围容器中的元素。

另请注意,如果您有严格的“无例外”规则,则必须避免使用STL,而且还要调用new [除了new nothrow种类]之外的所有调用 - 详情请参阅下文

另一种情况是异常“非常糟糕”,这就是从C调用C ++代码的地方 - 在这种情况下,将C ++中的异常“泄漏”到C代码中是未定义的行为(因为运行时在这种情况下,当走上堆栈找到处理程序时,我不知道如何处理异常。)

如果规则严格“你不能在C ++中使用任何可能引发异常的功能”,那么几乎所有的标准模板库(以及更多)都超出了范围。你将不得不在网上搜索其他替代方案[抱歉,这里不能提供任何有意义的帮助]并写下很多这样的代码:

some_vector_that_without_exceptions<int> v;
...
result = v.insert(element);
if (result != GOOD) 
    ... whatever you do when you can't insert to vector ... 
else 
    ... continue as you were ... 

我喜欢在“没有转到,没有早期回归”的工作指导下编程 - 这是有道理的,但你确实得到了相当多的重复:

result = some_thing(...);
if (result != success)
{
   ... cleanup ...
}
else 
{
    result = next_thing(...);
    if (result != success)
    {
       ... same cleanup as above ... 
       ... clean up after next_thing ... 
    }
    else
    {
        ... more stuff like above ...
    }
}

一段时间之后变得相当繁琐,但有时候生活中会使用编码标准。

由于STL容器抛出异常的主要原因是newdelete,因此根据您在系统内存不足时实际希望发生的事情,可以编写自己的operator new(这里是一个简单的版本)可以解决这个问题:

void *operator new(size_t size)
{
    void *p = malloc(size);
    if (p == NULL) 
    { 
       ... do something, like report out of memory and exit ...
    }
    return p;
}

void operator delete(void *p)
{
    free(p);
}

// And similarly for new [] and delete [].

这将避免插入/调整大小的所有投掷行为,例如std::vectorstd::map [当然,std::vector::resize仍然会有throw标记,因为头文件不会知道你的operator new永远不会抛出异常 - 但实际上它不会发生,而且实际上这是STL容器在正常情况下抛出异常的唯一原因(也就是说,不是超出范围访问等。)