从技术上讲,除了雪人在已删除答案的 cmets 中建议的“不可能”之外的原始问题的答案。但是我确实希望我可以就解决方案提供一些建议,以及“无例外”政策背后的理念和思想,可以用来争论使用std::vector是一件好事,而不是一件事情避免。显然,由读者来决定这样的论点是否可能对作为个人和项目的读者产生积极或不那么积极的结果。
编码标准中“无例外”规则的目的通常是为了避免出现相当混乱的情况,即存在大量不同的异常,在不同的级别进行处理,并且代码变得相当难以阅读 - 它可以是很难管理,并且是“不得抛出异常”的合理理由。
如果这是目的(而不是例如“我们使用的编译器不支持异常,因为它是唯一支持我们需要编译的处理器 X”),那么我认为仍然应该允许使用std::vector 和std::map,也许在main [或类似的中心位置] 内有一个try ... catch,它可以捕获所有异常并以合理的用户友好方式报告异常,然后退出 - 因为你的如果您确实遇到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 容器抛出异常的主要原因是 new 和 delete,根据您在系统内存不足时实际希望发生的情况,您可以编写自己的 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::vector 或 std::map [虽然,当然,std::vector::resize 仍然会有一个 throw 标记,因为头文件不会知道你的operator new 永远不会抛出异常 - 但实际上,它不会发生,这实际上是 STL 容器“在正常情况下”抛出异常的唯一原因(即,不会超出范围访问等)。