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

📄 chapter08.html

📁 Thinking in c++ 2nd edition,c++编程思想(第2版)
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<font color=#0000ff>int</font> <font color=#0000ff>const</font>* v;
<font color=#0000ff>int</font> d = 1;
<font color=#0000ff>int</font>* <font color=#0000ff>const</font> w = &amp;d;
<font color=#0000ff>const</font> <font color=#0000ff>int</font>* <font color=#0000ff>const</font> x = &amp;d;  <font color=#009900>// (1)</font>
<font color=#0000ff>int</font> <font color=#0000ff>const</font>* <font color=#0000ff>const</font> x2 = &amp;d; <font color=#009900>// (2)</font>
<font color=#0000ff>int</font> main() {} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<A NAME="Heading256"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Formatting<BR><A NAME="Index1499"></A><A NAME="Index1500"></A><A NAME="Index1501"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This book makes a point of only putting
one pointer definition on a line, and initializing each pointer at the point of
definition whenever possible. Because of this, the formatting style of
&#8220;attaching&#8221; the &#8216;<B>*</B>&#8217; to the data type is
possible:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font>* u = &amp;i;</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><I>as if</I> <B>int*</B> were a discrete
type unto itself. This makes the code easier to understand, but unfortunately
that&#8217;s not actually the way things work. The &#8216;<B>*</B>&#8217; in
fact binds to the identifier, not the type. It can be placed anywhere between
the type name and the identifier. So you could do this:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>int</font> *u = &amp;i, v = 0;</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">which creates an <B>int* u</B>, as
before, and a non-pointer <B>int v</B>. Because readers often find this
confusing, it is best to follow the form shown in this
book.</FONT><A NAME="_Toc312373911"></A><A NAME="_Toc472654885"></A><BR></P></DIV>
<A NAME="Heading257"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Assignment and type checking</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">C++ is very particular about type
checking, and this extends to
<A NAME="Index1502"></A><A NAME="Index1503"></A>pointer assignments. You can
assign the address of a non-<B>const</B> object to a <B>const</B> pointer
because you&#8217;re simply promising not to change something that is OK to
change. However, you can&#8217;t assign the address of a <B>const</B> object to
a non-<B>const</B> pointer because then you&#8217;re saying you might change the
object via the pointer. Of course, you can always use a
<A NAME="Index1504"></A>cast to force such an assignment, but this is bad
programming practice because you are then breaking the <B>const</B>ness of the
object, along with any safety promised by the <B>const</B>. For
example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:PointerAssignment.cpp</font>
<font color=#0000ff>int</font> d = 1;
<font color=#0000ff>const</font> <font color=#0000ff>int</font> e = 2;
<font color=#0000ff>int</font>* u = &amp;d; <font color=#009900>// OK -- d not const</font>
<font color=#009900>//! int* v = &amp;e; // Illegal -- e const</font>
<font color=#0000ff>int</font>* w = (<font color=#0000ff>int</font>*)&amp;e; <font color=#009900>// Legal but bad practice</font>
<font color=#0000ff>int</font> main() {} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Although C++ helps prevent errors it does
not protect you from yourself if you want to break the safety
mechanisms.</FONT><BR></P></DIV>
<A NAME="Heading258"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Character array literals</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The place where strict <B>const</B>ness
is not enforced is with character array
literals<A NAME="Index1505"></A><A NAME="Index1506"></A>. You can
say</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>char</font>* cp = <font color=#004488>"howdy"</font>;</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">and the compiler will accept it without
complaint. This is technically an error because a character array literal
(<B>&#8220;howdy&#8221;</B> in this case) is created by the compiler as a
constant character array, and the result of the quoted character array is its
starting address in memory. Modifying any of the characters in the array is a
runtime error, although not all compilers enforce this
correctly.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So character array literals are actually
constant character arrays. Of course, the compiler lets you get away with
treating them as non-<B>const</B> because there&#8217;s so much existing C code
that relies on this. However, if you try to change the values in a character
array literal, the behavior is undefined, although it will probably work on many
machines.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you want to be able to modify the
string, put it in an array:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>char</font> cp[] = <font color=#004488>"howdy"</font>;</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since compilers often don&#8217;t enforce
the difference you won&#8217;t be reminded to use this latter form and so the
point becomes rather
subtle.</FONT><A NAME="_Toc305628677"></A><A NAME="_Toc312373912"></A><A NAME="_Toc472654886"></A><BR></P></DIV>
<A NAME="Heading259"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Function arguments <BR>&amp; return values</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The use of <B>const</B> to specify
function arguments <A NAME="Index1507"></A><A NAME="Index1508"></A>and return
values<A NAME="Index1509"></A> is another place where the concept of constants
can be confusing. If you are passing objects <I>by
value<A NAME="Index1510"></A></I>, specifying <B>const</B> has no meaning to the
client (it means that the passed argument cannot be modified inside the
function). If you are returning an object of a user-defined type by value as a
<B>const</B>, it means the returned value cannot be modified. If you are passing
and returning <I>addresses<A NAME="Index1511"></A></I>, <B>const</B> is a
promise that the destination of the address will not be
changed.</FONT><A NAME="_Toc312373913"></A><A NAME="_Toc472654887"></A><BR></P></DIV>
<A NAME="Heading260"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Passing by const value</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can specify that function arguments
are <B>const</B> when passing them by value, such as</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>void</font> f1(<font color=#0000ff>const</font> <font color=#0000ff>int</font> i) {
  i++; <font color=#009900>// Illegal -- compile-time error</font>
} </PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">but what does this mean? You&#8217;re
making a promise that the original value of the variable will not be changed by
the function <B>f1(&#160;)</B>. However, because the argument is passed by
value, you immediately make a copy of the original variable, so the promise to
the client is implicitly kept.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Inside the function, the <B>const</B>
takes on meaning: the argument cannot be changed. So it&#8217;s really a tool
for the creator of the function, and not the caller.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To avoid confusion to the caller, you can
make the argument a <A NAME="Index1512"></A><B>const</B> <I>inside</I> the
function, rather than in the argument list. You could do this with a pointer,
but a nicer syntax is achieved with the
<A NAME="Index1513"></A><I>reference</I>, a subject that will be fully developed
in Chapter 11. Briefly, a reference is like a constant pointer that is
automatically dereferenced, so it has the effect of being an alias to an object.
To create a reference, you use the <B>&amp;</B> in the definition. So the
non-confusing function definition looks like this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>void</font> f2(<font color=#0000ff>int</font> ic) {
  <font color=#0000ff>const</font> <font color=#0000ff>int</font>&amp; i = ic;
  i++;  <font color=#009900>// Illegal -- compile-time error</font>
} </PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Again, you&#8217;ll get an error message,
but this time the <B>const</B>ness of the local object is not part of the
function signature; it only has meaning to the implementation of the function
and therefore it&#8217;s hidden from the
client.</FONT><A NAME="_Toc312373914"></A><A NAME="_Toc472654888"></A><BR></P></DIV>
<A NAME="Heading261"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Returning by const
value<BR><A NAME="Index1514"></A><A NAME="Index1515"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A similar truth holds for the return
value. If you say that a function&#8217;s return value is
<B>const</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>const</font> <font color=#0000ff>int</font> g();</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">you are promising that the original
variable (inside the function frame) will not be modified. And again, because
you&#8217;re returning it by value, it&#8217;s copied so the original value
could never be modified via the return value.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At first, this can make the specification
of <B>const</B> seem meaningless. You can see the apparent lack of effect of
returning <B>const</B>s by value in this example: </FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:Constval.cpp</font>
<font color=#009900>// Returning consts by value</font>
<font color=#009900>// has no meaning for built-in types</font>

<font color=#0000ff>int</font> f3() { <font color=#0000ff>return</font> 1; }
<font color=#0000ff>const</font> <font color=#0000ff>int</font> f4() { <font color=#0000ff>return</font> 1; }

<font color=#0000ff>int</font> main() {
  <font color=#0000ff>const</font> <font color=#0000ff>int</font> j = f3(); <font color=#009900>// Works fine</font>
  <font color=#0000ff>int</font> k = f4(); <font color=#009900>// But this works fine too!</font>
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">For built-in types, it doesn&#8217;t
matter whether you return by value as a <B>const</B>, so you should avoid
confusing the client programmer and leave off the <B>const</B> when returning a
built-in type by value.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Returning by value as a <B>const</B>
becomes important when you&#8217;re dealing with user-defined types. If a
function returns a class object by value as a <B>const</B>, the return value of
that function cannot be an lvalue <A NAME="Index1516"></A>(that is, it cannot be
assigned to or otherwise modified). For example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C08:ConstReturnValues.cpp</font>
<font color=#009900>// Constant return by value</font>
<font color=#009900>// Result cannot be used as an lvalue</font>

<font color=#0000ff>class</font> X {
  <font color=#0000ff>int</font> i;
<font color=#0000ff>public</font>:
  X(<font color=#0000ff>int</font> ii = 0);
  <font color=#0000ff>void</font> modify();
};

X::X(<font color=#0000ff>int</font> ii) { i = ii; }

<font color=#0000ff>void</font> X::modify() { i++; }

X f5() {
  <font color=#0000ff>return</font> X();
}

<font color=#0000ff>const</font> X f6() {
  <font color=#0000ff>return</font> X();
}

<font color=#0000ff>void</font> f7(X&amp; x) { <font color=#009900>// Pass by non-const reference</font>
  x.modify();
}

<font color=#0000ff>int</font> main() {
  f5() = X(1); <font color=#009900>// OK -- non-const return value</font>
  f5().modify(); <font color=#009900>// OK</font>
<font color=#009900>//!  f7(f5()); // Causes warning or error</font>
<font color=#009900>// Causes compile-time errors:</font>
<font color=#009900>//!  f7(f5());</font>
<font color=#009900>//!  f6() = X(1);</font>
<font color=#009900>//!  f6().modify();</font>
<font color=#009900>//!  f7(f6());</font>
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

⌨️ 快捷键说明

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