⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 item_068.htm

📁 C++程序编写规范,适合C++中级读者
💻 HTM
📖 第 1 页 / 共 2 页
字号:

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>断言一般来说仅在调试模式下产生代码(当没有定义</span><span
lang=EN-US>NDEBUG</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>宏时),因此在发行版中它们是不存在的。所以你可以大量地用它来检测想检测的各种东西。绝对不要在</span><span
lang=EN-US>assert</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>语句中写有副作用的表达式。在发行版中,如果定义了</span><span
lang=EN-US>NDEBUG</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>,那么</span><span lang=EN-US>assert</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>根本不会产生任何代码:</span><i style='mso-bidi-font-style:normal'><span
lang=EN-US><o:p></o:p></span></i></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US>assert( ++<span
class=SpellE>i</span> &lt; limit );<span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>糟糕:</span><span class=SpellE><span
lang=EN-US>i</span></span></i><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>仅在调试模式中才会被递增</span><span lang=EN-US><o:p></o:p></span></i></p>

<p class=MsoNormal><i style='mso-bidi-font-style:normal'><span lang=EN-US><o:p>&nbsp;</o:p></span></i></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>根据信息理论,一个事件所包含的信息量与该事件发生的几率成反比。因此,</span><span
lang=EN-US>assert</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>发生的几率越小,当它确实发生时它所包含的信息量就越多。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>要避免</span><span lang=EN-US>assert(false)</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,应该优先使用</span><span lang=EN-US>assert( !&quot;informational
message&quot;)</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>。大多数编译器会将该字符串输出到它们的错误输出中,而这是非常有用的。还可以考虑在更复杂的断言中加入</span><span
lang=EN-US>&amp;&amp; &quot;informational message&quot;</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,尤其是这可以取代注释。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>请考虑定义自己的</span><span lang=EN-US>assert</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>。标准的</span><span lang=EN-US>assert</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>在标准输出设备上输出一条信息后就粗暴地退出程序。你的开发环境可能会提供增强的调试功能,例如,可能允许自动地启动一个交互式调试器。如果是这样,那么你可能希望定义自己的</span><span
lang=EN-US>MYASSERT</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>宏来使用此类功能。自定义的断言也可以用来保留大多数的断言,即使在发行版中(最好不要因为性能的原因而禁用错误检测,除非事实证明确实需要,请参见第</span><span
lang=EN-US>8</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>条),另外如果断言工具可以区分不同“级别”的断言,那也是非常有用的,因为某些“级别”的断言可以保留在发行版中。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>如果编程语言的表达能力足够强,那么通常有许多断言可以在编译期检测。例如,你的整个设计可能依赖于每个</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>具有一个非零的</span><span
lang=EN-US>id_</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>。理想情况下,编译器会静态地分析</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的构造函数和成员,并验证该前提始终是成立的。并不存在如此智能的编译器,但你可以在</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的实现中加入</span><span
lang=EN-US>assert( id_ != 0 )</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>来确保</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的有效性:</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE>unsigned</span> <span class=SpellE>int</span> <span class=SpellE>Employee::GetID</span>()
{</span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;&nbsp;&nbsp; </span></span><span class=GramE><span
lang=EN-US style='font-family:"Arial Black"'>assert(</span></span><span
lang=EN-US style='font-family:"Arial Black"'> id_ != 0 &amp;&amp; “</span><span
style='font-family:宋体;mso-ascii-font-family:"Arial Black";mso-hansi-font-family:
"Arial Black"'>无效的</span><span lang=EN-US style='font-family:"Arial Black"'>Employee
ID</span><span style='font-family:宋体;mso-ascii-font-family:"Arial Black";
mso-hansi-font-family:"Arial Black"'>(必须为非零)</span><span lang=EN-US
style='font-family:"Arial Black"'>” );<o:p></o:p></span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>不要用断言来报告运行时候的错误(参见第</span><span
lang=EN-US>70</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>和</span><span lang=EN-US>72</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>条)。例如,不要用</span><span lang=EN-US>assert</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>来确保</span><span class=SpellE><span lang=EN-US>malloc</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>分配成功,窗口创建成功,或线程启动成功。但是,你可以用</span><span lang=EN-US>assert</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>来确保</span><span lang=EN-US>API</span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>函数确实如它们的文档所描述的那样执行。例如,如果你调用一个在文档中已说明为总是返回正值的</span><span
lang=EN-US>API</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>函数,但是怀疑该函数有错虫,那么你可以在每个调用之后加入</span><span
lang=EN-US>assert</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>语句来验证该函数的后置条件。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>不建议用抛出异常的方法来代替断言,即使标准的</span><span
class=SpellE><span lang=EN-US>std::logical_error</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>异常最开始是为此目的而设计的。使用异常来报告编程错误的主要缺点是你根本不希望进行栈展开——你希望启动调试器并停在发现错误的那一行,同时保持该行的状态不要改变。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>总之:你知道有一些错误可能会发生(第</span><span
lang=EN-US>69</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>到</span><span lang=EN-US>75</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>条)。对于其它不应该发生错误的,如果万一发生了,那么一定是程序员犯的错,这时别忘了用</span><span
lang=EN-US>assert</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>示例</span></b></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>示例:即使对最基本的假设也要使用</span><span lang=EN-US>assert</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>。</span></i><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>我们都曾听说过“绝对不可能发生”的断言,但却确实发生了。一次又一次,我们听到:“这个值肯定是正的!”“那个指针显然不会是空指针!”。即使是似乎不必要的重复,也务必要再次检查:软件开发是复杂的,变化是家常便饭,在一个不断变化的程序中,任何事情都有可能发生。断言会验证今天你认为“显然成立”的假设在今后依然成立。对似乎不必要的重复,请务必使用</span><span
lang=EN-US>assert</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>,因为类型系统无法替你强制(程序的不变性):</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span class=GramE><span
lang=EN-US>string</span></span><span lang=EN-US> <span class=SpellE>Date::DayOfWeek</span>()
const {</span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;&nbsp;&nbsp; </span></span><span lang=EN-US
style='font-family:"Arial Black"'>assert( day_ &gt; 0 &amp;&amp; day_ &lt;= 31
);</span><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>对不变性所做的检查</span><span lang=EN-US><o:p></o:p></span></i></p>

<p class=MsoNormal style='text-indent:36.0pt'><i style='mso-bidi-font-style:
normal'><span lang=EN-US><span style='mso-spacerun:yes'>&nbsp;&nbsp;&nbsp;
</span></span></i><span class=GramE><span lang=EN-US style='font-family:"Arial Black"'>assert(</span></span><span
lang=EN-US style='font-family:"Arial Black"'> month_ &gt; 0 &amp;&amp; month_
&lt;= 12 );<o:p></o:p></span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;&nbsp;&nbsp; </span><i style='mso-bidi-font-style:
normal'>// ...<o:p></o:p></i></span></p>

<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

</div>

</body>

</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -