我应该声明一个方法 no除非它在正确使用时永远不会抛出
Should I declare a method noexcept if it never throws when used correctly?
我正在实现一个队列,我想知道,当用户滥用容器时我该怎么办?
例如,我有两个方法,Front 和 Pop,只要它们不在空队列上调用,它们就不会抛出(我static_assert所包含元素的析构函数是 noexcept)。我可以向这些添加检查,如果它们在空队列中被调用,则会抛出,但是我无法定义它们,除非。
我在想声明这些 noexexcept 是有意义的,然后说在空队列上调用时行为是未定义的(我提供了 Size 和 Empty 方法供用户检查)。然后,我可以仅在调试版本上添加检查,因此它在误用时调用在调试中终止,并尝试在发布时破坏或取消引用缺少的元素。我想知道更好的方法是什么。
在考虑了接受的答案后,我决定遵循标准。Vector 的pop_back没有标记为 noexcept 并且与我的 Pop 具有相同的语义,所以我也不会将其标记为 noexcept 。一般来说,会尽量避免将狭隘的合同设置为不例外。
这不是一个简单的问题。在一般情况下,在C++中,您将记录您的合约,说明除非容器为非空,否则行为是未定义的。这意味着脱离上下文的调用可能会导致任何可能的行为。然后,在此类接口中使用 noexcept
会限制任何可能行为的范围:它是不涉及跨边界引发异常的任何可能行为。
为什么这很重要?在我工作的地方,我们使用BSL,它大致是扩展C++03标准库的实现。 该库的一部分包括用于防御性编程和测试的实用程序。该库没有使用assert
,而是使用自己的断言BSLS_ASSERT
宏来验证合约违规。该库的构建使得用户代码可以控制触发断言时发生的情况,并且在测试驱动程序中有效地用于验证积极行为(组件执行其应执行的操作)和负面行为(它不执行不应执行的操作),而且还具有对合同违规的适当检查。为此,使用引发特定形式的异常的断言处理程序,然后测试驱动程序可以调用合约外并验证组件是否正在检查行为...
篇大论,重点是,如果具有窄协定(可以调用非合约)的函数被标记为noexcept
,因为实现不应该抛出(在容器上调用front()
),那么当调用合约外时,它不能抛出,并且上述机制不能用于验证组件是否会检测到合约违规。
这是 C++11 标准后期修订(就在批准之前)的部分原因,该标准以狭窄的合同从所有功能中删除noexcept
。您可以在此提案中阅读更多内容
- 理解boost::asio-async_read在无需读取内容时的行为
- 当回溯以零开始时,如何调试崩溃
- 为"adjacent"变量赋值时出现问题
- CMake-按正确顺序将项目与C运行时对象文件链接
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 在Ubuntu 16.04上安装Cilk时出现问题
- 编译时未启用intel oneApi CUDA支持
- QGraphicsPolygonItem在拖动时未更新QPolygonF坐标
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- curl_slist->next 永远不会为空,因此当循环卡住时
- GRPC C 称为PloteimionQueue关闭,但PostemionQueue.Next在有待处理事件时永远阻
- 当存在移动构造函数时,确保复制构造函数永远不会调用
- 有没有一种方法可以在编译时加载到omp.h中,因此机器永远不需要在运行时获取它
- 当给定一个字符串时,为什么while会永远循环
- 当其他线程正在等待读取时,写入串口将永远阻塞
- 创建boost线程时,Shared_ptr永远不会释放
- 如何确保constexpr函数在运行时永远不会被调用