0

我正在写一个 C++ 类。它的一些字段是 STL 容器,有些不是。在编写方法时我开始想,我应该如何处理传递给方法的无效值?例如,某些方法或多或少是 STL 容器方法的包装器。当传递无效的迭代器时,许多 STL 方法只是具有“未定义的行为”。我想是这样的,因为它允许 STL 代码忽略这些情况,从而更快。

但是对于更高级别的代码,我该怎么办?当发生意外错误时,我确实会抛出异常,例如开发人员犯的错误导致的错误。但在这种情况下,参数值取决于接口用户,而不是实现者。我可以忽略无效的参数和无效的迭代器等,并将问题“传递”给较低级别​​的函数,这将产生未定义的行为,但我也可以抛出异常或至少找到某种方法来报告错误。

最好的办法是什么?

示例:我有一个表示树节点的类,它有一个 add_child() 方法,它采用 std::shared_ptr 参数。我应该检查该值还是让用户确保没有通过 nullptr?或者对于无效的迭代器,将其传递给 STL 方法或报错?如果我应该报告 - 例外是正确的解决方案吗?

4

2 回答 2

2

我认为无法给出一个普遍的答案。太多的事情影响了你没有提到的决定:首先,你是在开发库还是应用程序?

在第一种情况下,应该优先考虑灵活性,最好的选择通常是设计你的界面,让客户做出决定。由于您不知道哪些客户将使用您的课程以及他们将有哪些要求,因此最好尽可能少做假设。例如,如果您的客户有严格的性能要求,他们将不愿意支付额外边界检查的性能损失。基本上,这也是 STL 也不执行绑定检查的原因。

在第二种情况下,它取决于您的应用程序的性能要求以及您的类必须提供的异常安全保证。哪些操作需要不抛出?您是否允许或计划在 STL 容器中使用您的类?是否会在你的应用程序的最关键部分使用它,这样在这个类的算法中小的性能提升会影响你的应用程序的整体执行时间?

没有“普遍最佳的设计”之类的东西。工程就是根据手头的特定情况找到正确的折衷方案,软件工程也不例外。

于 2013-02-08T18:00:07.693 回答
-1

在这种情况下,我会使用如下断言:

assert(i < vec.size());
return vec[i];

这样,如果使用 NDEBUG 标志编译程序,您将获得最高性能并且无需检查。在开发过程中,您可能会在运行时出错并调试您的代码。断言宏可用于#include < cassert >。

于 2013-02-08T18:04:50.617 回答