是在传递给库函数之前检查值更好,还是捕获抛出的异常更好
Is it better to check values before passing to a library function, or catch a thrown exception?
假设我正在使用一个库,该库具有一个接受字符串参数的函数to_int
。如果字符串是数字的字符表示,则此函数返回int,例如"23"
将返回23
。如果字符串不是数字,它将抛出一个std::runtime_error
。更好的做法是:
if(is_all_digits(str))
x = to_int(str);
else
output("not an int, idiot. Try again");
或
try
{
x = to_int(str);
}
catch(...)
{
output("not an int, idiot. Try again");
}
有几种不同的错误处理技术,每种技术都有优缺点。
让我们考虑一个函数getAllElements()
,它获取一个包含一些元素的容器。
现在,这可能会产生一个错误(数据库连接或其他什么(。您现在可以选择
Errorcode getAllElements(std::vector<...> & cont);
或
std::vector<...> getAllElements(); //throws exceptions
这通常是一个一般的设计问题,取决于具体情况。出于多种原因,我更喜欢有例外的那一种。我可以分配,不需要预先确定的容器
auto elements = getAllElements();
下一件事是你将在哪里处理你的错误?如果像上面堆栈中的5个函数那样处理它们,那么每次都必须检查错误代码,并将其提供给下一个函数。异常将自动传播,直到有人发现并能够处理它
不过,例外情况也有一些不利之处。它们会导致更大的二进制文件,并且在抛出异常时速度较慢。在游戏开发中,通常不会因为这一点而使用任何例外(请收听以下内容了解更多信息:http://cppcast.com/2016/10/guy-davidson/他们讨论了为什么不使用异常。不过,我目前没有时间戳。(
在特殊情况下也应使用例外情况。你不能立即处理错误,必须在更高的地方处理。
因此,如果您不需要高性能/小二进制文件,我建议在有用的地方使用异常。它们可能导致键入更少的代码(如检查返回代码(,从而减少引入错误的位置。
以下也是关于CppCon 2016错误处理机制的一个很好的讨论:CppCon 2016:Patrice Roy"异常情况">
这个问题没有单一的答案,因为它取决于程序作为一个整体如何处理错误输入,以及在检测到错误时是否能够合理地恢复(无论这些错误是使用返回码还是通过抛出异常报告的(。
每个调用to_int()
的函数都能立即从错误输入中恢复吗?如果没有,最好允许抛出异常。。。。因此它展开堆栈,直到有某个调用者(具有try/catch
块(可以从错误中恢复为止。
如果您有许多调用to_int()
的函数,您想对每个函数进行检查吗?如果是这样,就会导致大量的代码重复。
如果您有一个调用to_int()
的函数,它可以立即从错误中恢复,而其他函数则不能?
如果您想向调用者报告错误(例如,允许比编写错误字符串更实质的内容(,该怎么办?
什么是没有is_all_digits()
功能的?如果没有,如果您以错过to_int()
将检测到的一些错误的方式实现它,该怎么办?然后你就有了两个世界中最糟糕的一个——做错误检查试图防止抛出异常,但函数无论如何都会抛出异常。例如,可能有一些全局设置导致to_int()
只接受八进制数字(在0
到7
的范围内(,但is_all_digits()
函数认为所有十进制数字都是有效的。
更一般地说,真正的需要是定义一个适用于整个程序的错误处理策略。试图根据单个函数的使用情况来决定是抛出异常还是不抛出异常,这完全没有意义。
如果您的程序使用异常报告错误是有意义的(例如,在main()
中有一个集中的try/catch
块,因此所有错误都会传播到调用堆栈上,因此main()
会全局实现恢复(,那么抛出异常。如果程序中的每个函数都能检测到错误并在现场静默处理,那么就避免出现异常。
我提倡的是让狗(你的程序(摇尾巴(关于如何处理错误的低级决策(。你的问题本质上是问让尾巴摇狗是否合适。
如果捕获的异常确实是特定的,那么您可以使用特定的try-catch(使用通用try-catch不是一个好主意,因为您隐藏了一堆其他可能的错误(
一般来说,我倾向于在将字符串传递给函数之前检查它。
当您使用库或API时,您希望它能防止您的错误使用和其他错误。
函数的作用是控制给定参数的完整性,并引发异常。
请注意,在开发代码时也可以使用断言,然后在二进制产品中禁用断言。
- C++:将控制台输出存储在宏中更好吗
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 初始化具有非默认构造函数的std::数组项的更好方法
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 为什么新的随机库比std::rand()更好
- 寻找一种更好的方法来表示无符号字符数组
- 哪种方法更好,性能明智
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 什么是更好的做法?通过指针或标识符传递类成员?
- 寻求更好地理解标准::访问
- 线程消息传递或更好:在"大师班"中访问其他班级的成员
- 有没有更好的方法来处理异常? try-catch块真的很丑
- 如何更好地检查两个 char 变量是否在一组值中?
- 有没有更好的方法对C++中的三个整数进行排序?
- 什么模板用法在阶乘中更好
- 什么时候在 c++ 中使用 exit() 与异常更好?
- C 向量异常处理:哪一种是抛出out_of_range()的更好方法以及原因
- 我如何从boost ::异常获得更好的诊断信息
- 在for循环内部使用时,是否存在任何异常甚至极端的情况,即后增量实际上比预增量更好
- 是在传递给库函数之前检查值更好,还是捕获抛出的异常更好