2

我正在编写一个程序,在其中创建了一个 std::vector 的 POD 结构。结构的成员之一是唯一标识符。

为了能够使用 std::binary_search 我必须为结构实现 operator<。按照这里的指导方针,我正在为 ==、!=、<、>、>= 和 <= 编写完整的重载集。

这提出了一个我不知道如何处理的问题。向量将按我分配给每个结构的唯一 ID 排序。如果两个结构具有相同的标识符,则它们是相同的。但是,在我看来,如果两个结构具有相同的标识符但其他成员中的数据不同,则可能会出现这种情况。

这不应该发生。然后让比较运算符检查其余字段并在它们不同但 ID 相同时抛出异常是否合适?什么样的例外最合适?

4

5 回答 5

7

这只是SCombinator 答案的扩展。

你说“这不应该发生”的事实。意味着您要使用断言,而不是异常(或两者的组合)。异常会隐藏错误 - 好吧,不是隐藏,但您将能够捕获它并继续。它更适合您没有真正计划的特殊情况 - 例如,您正试图打开一个不存在的文件。文件丢失并不是逻辑的一部分,而是您的小兄弟不小心删除了您的文件,或者认为它是病毒的侵略性防病毒软件,或者其他什么 - 这只是一种特殊情况。

如果成员具有相同 ID 但其他方面不同是不应该发生的事情,这基本上是一个断言。这是逻辑的一部分——如果你愿意的话,它是要求的一部分。抛出异常只是指出了这一点,但实际上并没有一种方法可以从中恢复。当你意识到有些不对劲时,已经晚了 2 点。您有两个具有相同 id 但不同的对象,您不知道哪个是正确的,您不知道为什么存在不正确的对象,等等。你可能甚至不想从中恢复过来。应用程序已经处于错误状态 - 两个相互矛盾的对象已经存在。您的应用程序处于不可恢复状态 - 如果您继续使用它,您可能会得到错误的结果或更糟。

如果不是关键断言,也可以事后抛出异常,提供干净的方式来关闭应用程序,但这只是美化。

一般来说,我遵循一个简单的规则——如果这是在特殊情况下可能发生的事情,我会使用例外。如果这是不应该发生的事情,并且如果确实发生了,则意味着代码中的逻辑存在严重错误,我会使用断言(并且可能会强制崩溃)。

于 2012-12-07T01:01:53.633 回答
2

好吧,你必须问自己几个问题:

1)这是否可能在测试期间发生(即发出错误信号)但在正常执行期间永远不会发生?如果答案是肯定的,请使用assert.

2)这是否会在正常运行时发生,如果是,程序能否恢复并继续执行?如果答案是肯定的,则抛出一个错误,捕获并处理它。

3)这是否会在正常运行时发生并且不可恢复?如果是,请调用abort或类似 ( exit, terminate) 或抛出您不会处理的异常。

于 2012-12-07T00:58:39.543 回答
2

如果这样的事情是一个逻辑错误,您可能应该使用assert.

于 2012-12-07T00:51:29.137 回答
1

创建数据时应拒绝不良数据。排除错误不是比较运算符的工作。这应该在程序进行任何严重的数据操作之前完成。所以这个问题的答案是否定的,operator==operator!=应该对坏数据抛出异常;编写它们时应该假设传递给它们的数据是有效的。

于 2012-12-07T14:07:32.907 回答
0

您可以只使用map用二叉搜索树实现的 a,尽管您会复制id. 再说一次,您甚至不需要将 存储id在结构中,因为它们应该是唯一的。

// Example POD struct.
struct MyStruct
{
  int id; // Redundant.
  char a;     
}

std::map<int, MyStruct> myMap;
MyStruct m; m.id = 1;
myMap[m.id] = m;
// Or simply..
myMap[1] = m;
于 2012-12-07T00:58:14.260 回答