【发布时间】:2020-10-18 01:37:01
【问题描述】:
我目前正在构建嵌入式系统并使用现代 C++ 编译器。 虽然我在技术上可以在给定资源(ARM7,超过 10M RAM)中进行异常处理,但我认为异常不是处理此类事情的正确工具,并且使用异常需要 RTTI,这反过来会导致代码膨胀。
为了保持 C++ 风格,我想使用 std::error_code(或类似的更多数据),因为我确实喜欢这个概念。
但是,对于如何实际使用它们似乎没有任何共识。我见过至少四种在函数调用之间传递它们的不同方式,其中两种具有多种语义。
-
通过指针作为参数传递
void somefunction(Args..., std::error_code* error);这是我不经常看到的方式,也是我最不喜欢的方式。它使返回类型完全可用,并且(通常但不总是)传递
nullptr导致正常的抛出行为。 -
通过引用作为参数传递
void somefunction(Args..., std::error_code& error);这是我更喜欢的一个。它使
returnvalue完全可用,并明确指出error_code不是可选的。 -
按值返回
std::error_code somefunction(Ret& out <= if used, Args...);我经常看到这个,但不是很喜欢它,因为它会耗尽你的返回值,而且我通常不喜欢“输出参数”,除非没有办法绕过它们。
-
返回
std::variant<Ret, std::error_code>std::variant<Ret, std::error_code> somefunction(Args...);这允许返回值,但使访问值和错误更加困难。此外,它使调用函数的代码更加冗长。
语义
如果 error_code 被传递,我已经看到了语义不同的方式 1 和 2。
- 启动时清除并设置错误
- 仅在出错时设置
- 如果
error_code为“设置”,则在开始时右转
如果您想减少调用代码中的错误检查,最后一种方法非常好。因为您可以将一个 error_code 传递给多个函数,而无需在两者之间进行检查,并且第一个错误之后的所有内容都不会执行,类似于异常的执行方式。
我个人更喜欢方式2的检查和返回,但是我可能有偏见。
有一些推荐/普遍接受的方法吗?
【问题讨论】:
-
你好。也许有点离题,但我会使用异常。您可以“自定义”它们传输您自己的错误代码,对函数原型没有“影响”,并且您可以肯定,如果有人忘记检查“返回”的错误代码,代码将崩溃(在开发阶段)。调用者代码也更干净,您可以在快乐路径(无错误)和异常处理路径之间拆分,而无需在每个函数调用位置测试返回的错误代码
-
问题是我可能必须将部分或全部应用程序移植到低规格平台,在这种情况下可能没有足够的空间来容纳异常版本(这会为异常添加大量代码处理和 rtti)。
-
我认为指针是这个例子中的方法,通过引用也很好,但这也只是我的偏见,我认为没有对错。
-
为什么异常处理需要RTTI?我认为这些是独立的属性。
-
@MarkRansom 因为你可能会抛出
std::runtime_error并抓住const std::exception&。编译器(或者确切地说是异常实现)需要一种方法来确定它们是否匹配,并且它们使用 rtti 这样做(类似于 dynamic_cast 所做的)。您可以禁用 rtti 并使用异常,但这只会禁用前端,但仍会发出实际的 rtti 信息和后端函数。
标签: c++ error-code