C++ 运算符应==或!=把这个箱子扔进去?

C++ 运算符应==或!=把这个箱子扔进去?,c++,exception,operator-overloading,C++,Exception,Operator Overloading,我正在写一个程序,在那里我创建了一个POD结构的std::vector。结构的一个成员是唯一标识符 为了能够使用std::binary_search,我必须为结构实现操作符=编写全套重载如果这是一个逻辑错误,你可能应该使用一个断言你可以使用一个映射,它是用一个二进制搜索树实现的,尽管你会复制一个id。同样,您甚至不需要在结构中存储id,因为它们应该是唯一的 // Example POD struct. struct MyStruct { int id; // Redundant. cha

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


为了能够使用std::binary_search,我必须为结构实现操作符<。按照指导原则,我正在为==,!=,>=编写全套重载如果这是一个逻辑错误,你可能应该使用一个
断言
你可以使用一个
映射
,它是用一个二进制搜索树实现的,尽管你会复制一个
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;
//示例POD结构。
结构MyStruct
{
int id;//冗余。
字符a;
}
std::map myMap;
我的结构;m、 id=1;
myMap[m.id]=m;
//或者干脆。。
myMap[1]=m;

好吧,你得问自己几个问题:

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

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


3) 这是否会在正常运行时发生,并且是不可恢复的?如果是,则调用
中止
或类似的操作(
退出,终止
)或抛出一个您不打算处理的异常。

这只是对

事实上,您说过“这永远不会发生”,这意味着您希望使用断言,而不是异常(或两者的组合)。异常会隐藏错误——好吧,不是隐藏,但是您可以捕获它并继续。它更适合于您没有真正计划的特殊情况—例如,您试图打开一个不存在的文件。文件丢失并不是逻辑的一部分,是你的弟弟不小心删除了你的文件,或者是一个攻击性的反病毒认为这是病毒,或者其他什么——这只是一个例外情况

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

如果它不是一个关键的断言,您也可以在之后抛出一个异常,并提供一种干净的方法来关闭应用程序,但这只是一种美化


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

创建数据时应拒绝坏数据。剔除错误不是比较操作员的工作;这应该在程序执行任何严重的数据操作之前完成。所以这个问题的答案是否定的,
operator==
operator=不应在错误数据上引发异常;编写它们时,应假定传递给它们的数据是有效的。

我认为基于id进行比较的
std::set
更适合此任务。如果希望此条件在运行时可恢复,则
throw
将是合适的。如果不是的话,
assert
可能是一个更好的选择。@chris我选择std::vector,因为我需要连续的内存。我不知道set(或任何其他订购的容器)提供了这种保证。这里的比较是一种误导。如果这两个结构不应该存在共享唯一标识符的结构,为什么要等到比较它们才能发现呢?将此类型的构造函数设为私有,并提供一个工厂函数来保证它。@gmannick同一个结构的两个副本存在不是一个错误。错误在于存在两个共享ID但信息不同的结构。如果我这样做了,结构就不再是PODs了。在这里使用assert是正确的,但是您可能想进一步说明为什么,为什么它比在这种情况下使用异常更好。谢谢。不过,为了澄清一点,如果ID相同而成员不同,则会发生错误,而不是相反。@Kian啊,好的。现在好多了?(但这并没有改变推理):)是的,谢谢你的解释。它确实能让我们更清楚地知道何时使用每一种方法。要是有那么简单就好了。您如何判断某些错误是否只发生在测试期间,而不会发生在正常执行期间?我想,要么希望是最好的,要么完全停止使用assert。(我的意思是使用完整的测试而不是断言。)这并不总是简单的。但有时这是可能的。