相关疑难解决方法(0)

为什么要保守地使用例外?

我经常看到/听到人们说异常应该很少使用,但永远不解释原因.虽然这可能是真的,但理由通常是一种愚蠢:"它被称为例外的原因",对我来说,这似乎是一种不应被一位受人尊敬的程序员/工程师接受的解释.

可以使用异常来解决一系列问题.为什么将它们用于控制流程是不明智的?对它们的使用方式保持格外保守的理念是什么?语义?性能?复杂?美学?惯例?

我之前已经看过一些关于性能的分析,但是在与某些系统相关且与其他系统无关的水平上.

同样,我不一定不同意他们应该在特殊情况下得救,但我想知道共识的理由是什么(如果这样的事情存在的话).

c++ exception

78
推荐指数
13
解决办法
9479
查看次数

在没有异常的情况下,C++异常以什么方式减慢代码?

我已经读过,使用C++异常进行异常处理有一些开销,而不是检查返回值.我只是谈论没有抛出异常时产生的开销.我还假设您需要实现实际检查返回值的代码并执行相应的操作,无论它与catch块的作用相同.并且,将异常对象与内部45个状态变量抛出的代码与为每个错误返回负整数的代码进行比较也是不公平的.

我不是仅仅基于哪个可以更快地执行来构建支持或反对C++异常的情况.我听到有人最近提出这样的情况:一旦你考虑了检查返回值和处理错误所需的所有额外簿记代码,使用异常的代码应该像基于返回代码的代码一样快.我错过了什么?

c++ exception overhead

54
推荐指数
3
解决办法
1万
查看次数

例外和错误代码:以正确的方式混合它们

我正在开发一个C++加密狗通信库.该库将提供一个统一的接口,以与一系列远程代码执行加密狗(如SenseLock,KEYLOK,Guardant Code)进行通信.

加密狗基于智能卡技术,具有内部文件系统和RAM.

典型的操作例程包括(1)枚举连接到USB端口的加密狗,(2)连接到所选择的加密狗,(3)执行命名模块传递输入和收集输出数据.

嗯,所有这些阶段最终都会出错,这是微不足道的.可能有很多情况,但最常见的是:

  • 找不到加密狗(肯定是一个致命的案例).
  • 加密狗连接失败(致命案例).
  • 在加密狗(?)中找不到指定的执行模块.
  • 请求的操作因超时(?)而失败.
  • 请求的操作需要授权(我认为是可恢复的案例).
  • 在加密狗中执行模块时发生内存错误(肯定是致命的情况).
  • 加密狗中发生文件系统错误(肯定是致命的情况).

? - 我不知道案件是否被认为是致命的.

我仍在决定是否抛出异常,返回错误代码,或为两种情况实现方法.

问题是:

  1. 异常是否完全替换了错误代码,或者我只需要将它们用于"致命案例"?
  2. 混合两种范例(例外和错误代码)被认为是一个好主意吗?
  3. 为用户提供两种概念是否是个好主意?
  4. 混合概念的异常和错误代码是否有任何好的例子?
  5. 你会如何实现这个?

更新1.

从不同的角度看更多意见会很有意思,所以我决定在这个问题上增加100点声望.

c++ error-handling exception

25
推荐指数
6
解决办法
7400
查看次数

缺点是C++中的异常

我正在阅读谷歌C++风格指南,并在例外部分感到困惑.根据指南,使用它的一个缺点是:

异常安全需要RAII和不同的编码实践.需要大量的支持机制才能使编写正确的异常安全代码变得容易.此外,为了避免要求读者理解整个调用图,异常安全代码必须将写入持久状态的逻辑隔离到"提交"阶段.这将带来好处和成本(可能是您被迫混淆代码以隔离提交的地方).允许例外将迫使我们总是支付这些费用,即使它们不值得

具体来说,我不明白的陈述是这样的:

(...)异常安全代码必须将写入持久状态的逻辑隔离到"提交"阶段.

还有这个:

(...)也许你被迫混淆代码来隔离提交(...).

我想我不习惯术语"持久状态","提交阶段","混淆代码以隔离提交".关于这些术语的一些小解释,例子或参考可能是很好的,也可能是为什么这是真的.

c++

14
推荐指数
3
解决办法
6479
查看次数

何时使用 std::expected 而不是异常

我什么时候应该使用std::expected异常?什么时候应该使用异常?以这个函数为例:

int parse_int(std::string_view str) {
    if (str.empty()) {
        throw std::invalid_argument("string must not be empty");
    }
    /* ... */
    if (/* result too large */) {
        throw std::out_of_range("value exceeds maximum for int");
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

我想在使用此函数时区分不同的错误,因此抛出不同类型的异常很有用。但是,我也可以这样做std::expected

enum class parse_error {
    empty_string,
    invalid_format,
    out_of_range
};

std::expected<int, parse_error> parse_int(std::string_view str) noexcept {
    if (str.empty()) {
        return std::unexpected(parse_error::empty_string);
    }
    /* ... */
    if (/* result too large */) {
        return std::unexpected(parse_error::out_of_range);
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

是否有任何理由使用std::expected异常(性能、代码大小、编译速度、ABI),或者只是风格偏好?

c++ error-handling exception c++23 std-expected

8
推荐指数
0
解决办法
697
查看次数

现代 C++:返回状态(正常/不正常)和错误(如果状态不正常)的函数的最佳方法是什么?

我们可以返回一个元组

std::pair<bool, std::string> fooFunction();
Run Code Online (Sandbox Code Playgroud)

但这使得创建返回值时代码变得多余,并强制调用者处理元组(在 c++17 中使用结构绑定很容易)

if ( okayCondition)
    return {true, {}}; 
else 
   return { false, "blabla error"};
Run Code Online (Sandbox Code Playgroud)

或者我们可以使用

std::optional<std::string> fooFunction();
Run Code Online (Sandbox Code Playgroud)

这对于返回 bool 的现有函数很有趣,因为由于 std::optional 运算符 bool,大多数调用者不需要更新

//Legacy code ok
if (fooFunction())
Run Code Online (Sandbox Code Playgroud)

我知道一种更重的方法,一个模板化的 ReturnStatus 类,它会在调用者不测试返回状态值的情况下抛出。
还有其他方法吗?

c++ c++11

5
推荐指数
1
解决办法
169
查看次数

哪个更好,抛出异常或返回非零值?

可能重复:
C++ - 返回代码异常的参数

在进行C++编程时,您有两种报告错误的选择.我想很多老师会建议你抛出一个异常,它是从std :: exception派生的.另一种可能更"C"形式的方法是返回非零值,因为零是"ERROR_SUCCESS".

确切地说,返回异常可以提供更多的错误和恢复信息; 虽然代码会膨胀一点,但在你的脑海中保持异常安全对我来说有点困难,至少.其他方式,如返回其他内容,将使报告错误更容易; 缺点是管理恢复将是一个可能很大的问题.

作为优秀的程序员,人们会不会考虑老板的意见?对我来说,我想返回一些非零值.

c++ exception

2
推荐指数
1
解决办法
3761
查看次数

标签 统计

c++ ×7

exception ×5

error-handling ×2

c++11 ×1

c++23 ×1

overhead ×1

std-expected ×1