返回空值或抛出异常
returning null or throwing an exception?
我有以下类型:
typedef QPair < QTime , QTime > CalculatedTimeSlotRange;
typedef QList < CalculatedTimeSlotRange > CalculatedTimeSlotRangeList;
typedef QHash < quint8 , CalculatedTimeSlotRangeList > TimeSlotsTable;
我有一个像下面这样的函数:
const CalculatedTimeSlotRangeList* TimeSlots::getCalculatedTimeSlotRangeList(const quint8 id) const
{
QHashIterator<quint8,CalculatedTimeSlotRangeList> it(mTimeSlotsTable);
while (it.hasNext()) {
it.next();
if(it.key() == id) {
return &it.value();
}
}
return NULL;
}
,你可以看到我的函数返回一个NULL
,如果它没有找到一个匹配id
的键。这是正确的吗?或者如果键不存在,我应该抛出一个异常?对于这种情况,我应该如何抛出异常?
在看到注释和答案后,我认为有必要指出,抛出异常或返回null并不重要。此事件暗示通过许多文件提供给程序的参数不正确。程序必须显示错误消息,并要求用户用正确的参数文件替换参数文件。那么哪种选择更好呢?异常指针或空指针,因为它们在上下文中的意思是一样的。如果问题和描述不能反映我的真实意图,请编辑。
问问你自己:如果你是使用这个函数的人,你希望它表现出哪种行为?这两种方法各有优缺点——如果抛出异常,则调用代码有责任了解这种可能性并在某个时候捕获异常,否则程序将abort(),这对用户来说与崩溃几乎是一样的。
另一方面,如果您的函数返回NULL,那么调用者有责任在继续之前检查返回值是否为空,否则他可能会因为空指针解引用而导致程序崩溃。此外,处理返回指向对象的指针的函数可能会因为对象所有权问题而令人困惑——调用者必须问自己,"我是否应该在使用完这个对象后删除它?"——如果这个问题的答案是错误的,将会导致崩溃或内存泄漏。
还有第三种您可能没有考虑过的选择:返回对虚拟对象的引用。使用该选项实现函数可能如下所示:
const CalculatedTimeSlotRangeList & TimeSlots::getCalculatedTimeSlotRangeList(const quint8 id) const
{
QHashIterator<quint8,CalculatedTimeSlotRangeList> it(mTimeSlotsTable);
while (it.hasNext()) {
it.next();
if(it.key() == id) {
return it.value();
}
}
static const CalculatedTimeSlotRangeList _dummyObject; // note: static to avoid dangling reference when returned!
return _dummyObject;
}
我喜欢这种方法,因为现在用户不必担心检查NULL, 和,他也不必担心正确处理异常。此函数将始终返回对有效的CalculatedTimeSlotRangeList的引用;在未找到的情况下,它将是一个空的/默认构造的;这(取决于您的特定用例)可能完全可以接受。
由于失败条件表明程序配置的致命条件,在您建议的选项中,我绝对建议抛出异常,因为这是一个真正的异常情况。
我认为invalid_argument
在这里是有意义的,所以你会#include <stdexcept>
,然后用throw std::invalid_argument("your error message about the bad configuration");
代替return
语句
- 从构造函数抛出异常时如何克服内存泄漏
- 函数如何通知用户它基于函数原型抛出异常?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- VisualStudios 会抛出异常,而代码块不会 [C++]
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- ZMQ::send() 抛出异常并终止 QNX 进程.为什么以及如何从中恢复?
- new(std::nothrow) int[n] 抛出异常
- 为什么g_object_set抛出异常(vcruntime140.dll)?
- 你能防止 std::regex 在无效表达式上抛出异常吗?
- C++子线程抛出异常
- 我们应该在抛出异常之前取消分配内存吗
- 有没有一种方法可以让OpenCLC++绑定为所有错误抛出异常
- 为什么访问模板化变体作为返回值抛出异常
- ATL/COM:为什么 CComSafeArray::GetCount() 会为空数组抛出异常
- c++如何处理抛出异常的初始值设定项
- 为什么当我在使用空 throw() 说明符指定的函数中抛出异常时没有调用 std::unexpected()
- 返回空值或抛出异常
- 空std::list在调用析构函数时抛出异常
- 为什么 std::string::substr 会抛出异常而不是返回空字符串
- 如何查明函数模板中的赋值操作符T是否抛出异常