📄 ref.html
字号:
<td>
<!-- Definition -->
<p>
<table border=4 cellpadding=10><tr>
<td bgcolor="#ffffff" class=defTable>
Warning: The similarity between the assignment operator = and the equality operator == is a common source of serious programming mistakes.</table>
<!-- End Definition -->
<p>
It is very unfortunate that, because of the heritage of C, a single typo like this may cause an almost undetectable programming error. Don't count on the compiler to flag the statement
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>x == 1;</pre>
</table>
<!-- End Code -->
or the conditional
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>if (x = 0)</pre>
</table>
<!-- End Code -->
as errors (some compilers will warn, but only at a high warning level). Some people try to prevent such errors by getting into the habit of reversing the order of equality testing against a constant. For instance
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>if (0 == x)</pre>
</table>
<!-- End Code -->
is safer than
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>if (x == 0)</pre>
</table>
<!-- End Code -->
because the omission of one of the equal signs will immediately cause a compiler error. I used to be one of the advocates of this style, but I changed my mind. I don't like a style that decreases the readability of code.
<p>
The <i>not-equal-to</i> relation is expressed using the operator !=, as in <var>x != 0</var>.
<p>
The <var>main</var> procedure tests the functionality of the sequencer. It pushes a few numbers onto the stack and then iterates through it. Notice how the object <var>TheStack</var> is passed to the constructor of the iterator. The compiler knows that what we really mean is a reference, because it has already seen the declaration of this constructor in the class definition of <var>IStack</var>. Since the constructor was declared to take a reference, the reference will automatically be passed.
<p>
When a formal argument of a method is specified as a reference, we say that this argument is passed by reference. When you call a method like that, you pass it a reference to a variable, and the method may change the value of that variable. This is in contrast to passing an argument by value. When you call a method that expects to get a variable by value, the method will not change the value of this variable. It will operate on a copy of its value.
<p>
Compare these two methods.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>class <span class=method>Dual</span>
{
void ByValue (int j)
{
++j;
cout << j << endl;
}
void ByRef (int & j)
{
++j;
cout << j << endl;
}
};
void <span class=method>main</span> ()
{
Dual dual;
int i = 1;
dual.ByValue (i);
cout << "After calling ByValue, i = " << i << endl;
dual.ByRef (i);
cout << "After calling ByRef, i = " << i << endl;
}</pre>
</table>
<!-- End Code -->
<p>
The first method does not change the value of <var>i</var>, the second does.
<p>
If you are worried about the fact that from the caller's point of view it is not obvious whether a reference was meant--don't! As a general rule, assume that objects are passed by reference, built-in types by value (the example above notwithstanding).
<p>
Only in some special cases will we pass objects by value, and it will be pretty obvious why (see: value classes). So, when reading most programs, you can safely assume that, when an object is passed to a function, it is passed by reference.
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>void <span class=method>main</span> ()
{
IStack TheStack;
TheStack.Push (1);
TheStack.Push (2);
TheStack.Push (3);
for ( StackSeq seq (TheStack);
!seq.AtEnd();
seq.Advance() )
{
cout << " " << seq.GetNum() << endl;
}
}</pre>
</table>
<!-- End Code -->
<p>
Let us follow the path of the reference. A reference to <var>TheStack</var> is passed to the constructor of <var>StackSeq</var> under the (read-only) alias of <var>stack</var>. This is a new temporary name for the object <var>TheStack</var>. This reference cannot be used to modify <var>TheStack</var> in any way, since it is declared <var>const</var>. Next, we initialize the reference data member <var>_stack</var> of the object <var>seq</var>. Again, this reference cannot be used to modify <var>TheStack</var>. From the time the object <var>seq</var> is constructed until the time it is destroyed, <var>_stack</var> will be a read-only alias for <var>TheStack</var>. The sequencer will know <var>TheStack</var> under the read-only alias <var>_stack</var>.
<p>
Notice the creative use of the for loop. We are taking advantage of the fact that the for-loop header contains a <i>statement</i>, an <i>expression</i>, and a <i>statement</i>. The first statement--loop <b><i>initialization</i></b>--is executed only once before entering the loop. In our case it contains the definition of the sequencer. The following expression--the loop <b><i>condition</i></b>--is tested every time the loop is (re-) entered. If the expression is true (non-zero) the iteration starts (or continues). When it is false, the loop is exited. In our case the condition is that the sequencer is not at the end. The third statement--the loop <i><b>increment</b></i>--is executed after every iteration. In our example it advances the sequencer. Notice that after a normal exit from the loop, the loop condition always ends up false.
<p>
Any of the three parts of the for-loop header may be empty. An infinite loop, for instance, is usually implemented like this:
<!-- Code -->
<table width="100%" cellspacing=10><tr>
<td class=codeTable>
<pre>for (;;) // do forever
{
// There must be some way out of here!
}</pre>
</table>
<!-- End Code -->
(Of course you can exit such loop using a <var>break</var> or a <var>return</var> statement.)
<p>
Here's a list of some of the operators that create Boolean values.
<p>
<table width=50% border=1>
<tr>
<td colspan=2><b>Equality Testing Operators</b>
<tr>
<td>== <td>equal to
<tr>
<td>!= <td>not equal to
<tr>
<td colspan=2><b>Relational Operators</b>
<tr>
<td>> <td>greater than
<tr>
<td>< <td>less than
<tr>
<td>>= <td>greater than or equal to
<tr>
<td><= <td>less than or equal to
<tr>
<td colspan=2><b>Logical Negation Operator</b>
<tr>
<td>! <td>not
</table>
</table>
<!-- End Main Table -->
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -