从lambda表达式中抛出异常,是一种不好的习惯吗?

3

我目前正在解析一个令牌队列:我写了一个lambda函数,如果queue.begin() == queue.end(),就会抛出异常,而不是为每个后续的pop()检查队列是否为空。我想知道这是一个好的、“适当”的实现,还是一般认为从lambda表达式中抛出异常是一种不好的实践?


2
如果您使用常规函数完成同样的工作,会有什么坏处吗? 我会说没有,因此答案是否定的。 - milleniumbug
3个回答

6

从lambda函数中抛出异常与从任何其他函数中抛出异常相同。

现在,如果在这种情况下抛出异常是一个好的实践,在我看来并不是。异常应该在异常情况下使用(例如,子弹穿过了您的CPU),而我不认为到达范围的末尾符合此类情况(即,异常情况)。


1
我同意这一点——不管从Lambda抛出异常是否是良好的实践,OP描述的情况听起来像是在使用异常来控制流程,这是好的做法。 - tsleyson
1
如果预期队列中应该有一个项目,但实际上没有,则属于异常情况。 - Richard Hodges
但是如果队列中没有预期的标记,则提供的数据不完整,抛出异常似乎是很自然的选择? - quiZ___
@quiZ___的短答案是:是的。 - 101010
1
我认为抛出异常的要求取决于情况和抽象级别。 - malintha

2

我认为这取决于你想要达到什么目的。我个人会将检查空队列的操作留给调用pop函数的函数。似乎没有理由通过异常来限制队列的功能。也许有一些情况下你需要处理空队列,但是对我来说,抛出异常并处理这种情况似乎会导致代码膨胀。

这只是我的个人偏好。


1
我在做一个项目时,思考了这个问题。 我同意那些说可以使用lambda表达式的答案,但最好只在特殊情况下使用(尤其是因为当抛出异常时,异常并不便宜)。 在我的情况下,我使用lambda表达式多次保存文件以升级它(所有保存的代码都相同,如果失败,我认为它是一个异常,因为它不应该发生)。 我的项目伪代码:
void upgradeFile(/* params */){

    std::string configVersion = readCurrentConfigVersion();

    auto fSaveFileAfterUpgrade = [](/* params */){
            if(!param1.saveFile(/*params*/)){
                throw std::runtime_error("My error Message");
            }
    };

    if(configVersion == "1.0"){

        const std::string versionAfterUpgrade = "1.1";

        // UPGRADE CODE...

        fSaveFileAfterUpgrade(/* params */);

        configVersion = versionAfterUpgrade;
    }

    if(configVersion == "1.1"){
        const std::string versionAfterUpgrade = "1.1a";

        // UPGRADE CODE...

        fSaveFileAfterUpgrade(/* params */);

        configVersion = versionAfterUpgrade;
    }
}

如果lambda表达式中发生异常,调用upgradeFile的函数将处理它(我在其上设置了try catch)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接