11

我在发布版本下找不到关于 Q_ASSERT 语义的明确声明。如果没有断言检查,那么断言表达式是否被评估?

考虑以下代码

Q_ASSERT(do_something_report_false_if_failed());

do_something_report_false_if_failed()在所有潜在的 Qt 构建配置下运行吗?这样做会更安全(即使更冗长且可读性更低):

bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)

后一种方法的缺点是 ASSERT 失败不那么冗长,但也许它更清楚地表明该语句已执行?

4

2 回答 2

19

内部的表达式Q_ASSERT不会在非调试构建配置中进行评估。

考虑下面来自Qt repo的源代码。

#if !defined(Q_ASSERT)
#  ifndef QT_NO_DEBUG
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  else
#    define Q_ASSERT(cond) qt_noop()    
#  endif    
#endif

如果QT_NO_DEBUG已定义,则将整个Q_ASSERT语句替换为 a qt_noop(),从而删除它先前包含的任何表达式。

永远不要依赖语句中的表达式产生的任何副作用Q_ASSERT。从技术上讲,仍然可以确保它QT_NO_DEBUG没有在特定的构建配置中定义,但这不是一个好主意™。

于 2012-09-24T21:52:12.250 回答
16

这在Qt5.5中似乎有所不同(但不是更早 - 请参阅Qt5.4):

#if !defined(Q_ASSERT)
#  if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
#    define Q_ASSERT(cond) do { } while ((false) && (cond))
#  else
#    define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
#  endif
#endif

我现在在 Visual Studio 2013 中收到很多“警告 C4127:条件表达式是常量”。

更新: Qt5.5 发行说明说:

Q_ASSERT 现在即使在释放模式下,当断言被禁用时也会扩展条件,尽管在无法访问的代码路径中。这解决了关于在发布模式下未使用的变量和函数的编译器警告,因为它们仅在断言中使用。不幸的是,通过#ifndef 隐藏这些函数和变量的代码库需要删除条件才能使用 Qt 5.5 进行编译。

于 2015-09-10T06:51:41.687 回答