为什么c++ assert()函数会给程序带来开销

Why will c++ assert() function brings overhead to program

我有实践用c++assert检查程序是否运行正常,比如这样:

cv::Mat im = imread("pic.jpg")
assert(!im);

这将检查图像是否被正确读取。这很有用,因为图像可能未正确放置在预期目录中,因此我们需要检查。我觉得用assert方便,但是人家说用assert会给程序带来开销,建议不要用。为什么 assert 会带来开销?在这种情况下检查的好做法是什么?

Why will c++ assert() function brings overhead to program

首先,assert 在技术上不是函数。是一个宏。

回答问题:视情况而定。如果禁用断言,则不会进行检查,因此不会产生开销。如果启用断言,那么与没有检查相比会有开销(除非编译器可以在编译时证明检查是不必要的)。

任何额外的代码都会增加程序的“开销”,例如增加执行时间、代码大小,可能还有 ram 大小。
使用 assert() 的代码也是如此(除了 assert() 仅完成其工作并且仅在活动时才使用任何资源的细节,即如果未使用 -DNDEBUG;归功于 DevSolar对于这个细节)。

两种代码,有和没有assert(),都被添加到程序中,因为它们当然是有目的的。

您已经清楚充分地描述了使用 assert() 的目的。
现在的问题不是它是否使用资源,而是你是否想达到目的,为此你可能愿意付出使用资源的代价。
由于您似乎很清楚这些好处,因此使用 assert().

似乎是一个合适的决定

如果您要求使用 assert() 的任何替代方法,答案是有 none 支持相同的目的而不使用任何资源。

您可能还需要考虑,如果您不再需要自检功能(在我看来通常永远不需要)并且真正关注“无开销”,那么您可以使用提到的开关删除资源消耗。

首先,assert()不是一个普通的函数。它是类似于此的宏:

#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition) /*implementation*/
#endif

如您所见,它仅在未定义 NDEBUG 时启用并执行某些操作。当您在 调试模式 中 运行 时,它用于对您的程序进行 额外 检查,以帮助查明错误(例如错误参数、不成立的不变量等)更快。

如果你像你展示的那样使用它,断言本身可能不会花费那么多性能,但因为我上面写的 - 它是调试工具 - 可能在代码库的许多地方使用。如果传递给 assert 的条件很复杂,确保评估它们可能需要时间(并且您的客户无需担心,因为这只会在调试模式下发生,因此它们不会受到影响 - NDEBUG 所有这些开销会消失)。

你不应该使用 assert() 来验证你想要 总是 验证的东西(也在 non-debug 模式下)。在这种情况下,这样做是正确的:

cv::Mat im = imread("pic.jpg")
if (!im) {
   /* handle error ... */
}