📄 ch3.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 3 -- References</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 3</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>References</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#IntroductiontoReferences" >Introduction to References</A>
<LI><A HREF="#UsingReferences" >Using References</A>
<LI><A HREF="#TheBackslashOperator" >The Backslash Operator</A>
<LI><A HREF="#ReferencesandArrays" >References and Arrays</A>
<LI><A HREF="#UsingMultidimensionalArrays" >Using Multidimensional Arrays</A>
<LI><A HREF="#ReferencestoSubroutines" >References to Subroutines</A>
<UL>
<LI><A HREF="#UsingSubroutineTemplates" >Using Subroutine Templates</A>
</UL>
<LI><A HREF="#ImplementingStateMachines" >Implementing State Machines</A>
<LI><A HREF="#PassingMoreThanOneArrayintoaSubro" >Passing More Than One Array into a Subroutine</A>
<UL>
<LI><A HREF="#PassbyValueorbyReference" >Pass by Value or by Reference?</A>
</UL>
<LI><A HREF="#ReferencestoFileHandles" >References to File Handles</A>
<UL>
<LI><A HREF="#WhatDoesthevariableOperatorDo" >What Does the <I>*variable</I> Operator Do?</A>
</UL>
<LI><A HREF="#UsingSymbolicReferences" >Using Symbolic References</A>
<UL>
<LI><A HREF="#DeclaringwithCurlyBraces" >Declaring with Curly Braces</A>
<LI><A HREF="#MultidimensionalAssociativeArrays" >Multidimensional Associative Arrays</A>
</UL>
<LI><A HREF="#StrictReferences" >Strict References</A>
<LI><A HREF="#ForMoreInformation" >For More Information</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
This chapter describes the use of Perl references and the concept
of pointers. It also shows you how to use references to create
fairly complex data structures and pass pointers, as well as how
to use pointers to subroutines and to pass parameters.
<H2><A NAME="IntroductiontoReferences"><FONT SIZE=5 COLOR=#FF0000>Introduction
to References</FONT></A></H2>
<P>
A <I>reference</I> is simply a pointer to <I>something</I>; it
is very similar to the concept of a <I>pointer</I> in C or PASCAL.
That <I>something</I> could be a Perl variable, array, hash, or
even a subroutine. A reference in your program is simply an address
to a value. How you use the value of that reference is really
up to you as the programmer and what the language lets you get
away with. In Perl, you can use the terms pointer and reference
interchangeably without any loss of meaning.
<P>
There are two types of references in Perl 5 with which you can
work: <I>symbolic </I>and <I>hard</I>.
<P>
A symbolic reference simply contains the name of a variable. Symbolic
references are useful for creating variable names and addressing
them at runtime. Basically, a symbolic reference is like the name
of a file or a soft link on a UNIX system. Hard references are
more like hard links in the file system; that is, a hard link
is merely another path to the same file. In Perl, a hard reference
is another name for a data item.
<P>
Hard references in Perl also keep track of the number of references
to items in an application. When the reference count becomes zero,
Perl automatically frees the item being referenced. If that item
happens to be a Perl object, the object is "destructed,"
that is, freed to the memory pool. Perl is object-oriented in
itself because everything in a Perl application is an object,
including the main package. When the main package terminates,
all other objects within the main object are also terminated.
Packages and modules in Perl further the ease of use of objects
in Perl. Perl modules are covered in <A HREF="ch4.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch4.htm" >Chapter 4</A>,
"Introduction to Perl Modules."
<P>
When you use a symbolic reference that does not exist, Perl creates
the variable for you and uses it. For variables that already exist,
the value of the variable is substituted instead of the <TT><FONT FACE="Courier">$variable
</FONT></TT>token. This substitution lets you construct variable
names from variable names.
<P>
Consider the following example:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$lang = "java";<BR>
$java = "coffee";<BR>
<BR>
print "${lang}\n";<BR>
print "hot${lang}\n";<BR>
print "$$lang \n"</FONT></TT>
</BLOCKQUOTE>
<P>
The third <TT><FONT FACE="Courier">print</FONT></TT> line is important.
<TT><FONT FACE="Courier">$$lang</FONT></TT> is first reduced to
<TT><FONT FACE="Courier">$java</FONT></TT>, then the Perl interpreter
will recognize that <TT><FONT FACE="Courier">$java</FONT></TT>
can also be reparsed, and the value of <TT><FONT FACE="Courier">$java</FONT></TT>,
<TT><FONT FACE="Courier">"coffee"</FONT></TT>, is used.
<P>
Symbolic references are created via the <TT><FONT FACE="Courier">${}</FONT></TT>
construct, so <TT><FONT FACE="Courier">${lang}</FONT></TT> translates
to <TT><FONT FACE="Courier">java</FONT></TT>, and <TT><FONT FACE="Courier">hot${java}</FONT></TT>
translates to <TT><FONT FACE="Courier">hotjava</FONT></TT>. If
you want to address a variable name <TT><FONT FACE="Courier">hotjava</FONT></TT>,
you could use the statement: <TT><FONT FACE="Courier">${hot${lang}}</FONT></TT>.
This would be interpreted as, "take the value in <TT><FONT FACE="Courier">$lang</FONT></TT>,
and append it to the word hot. Now take the constructed string
(<TT><FONT FACE="Courier">hotjava</FONT></TT>) and use it as a
name because there is a <TT><FONT FACE="Courier">${}</FONT></TT>
around it."
<P>
In other words, the value of the scalar produced by <TT><FONT FACE="Courier">$$lang</FONT></TT>
is taken to be the name of a new variable, and the variable at
<TT><FONT FACE="Courier">$java</FONT></TT> is used. Here's the
output from this example:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">java<BR>
hotjava<BR>
coffee</FONT></TT>
</BLOCKQUOTE>
<P>
Thus, the difference between a hard reference (<TT><FONT FACE="Courier">$lang</FONT></TT>)
and a symbolic reference (<TT><FONT FACE="Courier">$$lang</FONT></TT>)
is how the variable name is derived. In a hard reference, you
are referring to a variable's value directly. With a symbolic
reference, you are using another level of indirection by constructing
or deriving a symbol name from an existing variable.
<P>
References are easy to use in Perl as long as they are used as
scalars. To use hard references as anything but scalars, you have
to explicitly dereference the variable and tell it how to be used.
<H2><A NAME="UsingReferences"><FONT SIZE=5 COLOR=#FF0000>Using
References</FONT></A></H2>
<P>
A <I>scalar value</I> in this chapter refers to a variable, such
as <TT><FONT FACE="Courier">$pointer</FONT></TT>, that contains
one data item. This item is a scalar and any scalar may hold a
hard reference. Arrays and hashes contain scalars; therefore,
they can hold many references. Thus, with judicious use of arrays
and hashes, you can easily build complex data structures of different
combinations of arrays of arrays, arrays of hashes, hashes of
functions, and so on.
<P>
There are several ways to construct references, and you can have
references to just about anything-arrays, scalar variables, subroutines,
file handles, and, yes (to the delight of C programmers), even
to other references.
<P>
To use the value of <TT><FONT FACE="Courier">$pointer</FONT></TT>
as the pointer to an array, you reference the items in the array
as <TT><FONT FACE="Courier">@$pointer</FONT></TT>. The notation
<TT><FONT FACE="Courier">@$pointer</FONT></TT> roughly translates
to "take the value in <TT><FONT FACE="Courier">$pointer</FONT></TT>,
and then use this value as the address to an array." Similarly,
you use <TT><FONT FACE="Courier">%$pointer</FONT></TT> for hashes.
That is, "take the value of <TT><FONT FACE="Courier">$pointer</FONT></TT>
and interpret is as an address to a hash."
<H2><A NAME="TheBackslashOperator"><FONT SIZE=5 COLOR=#FF0000>The
Backslash Operator</FONT></A></H2>
<P>
Using the backslash operator is analogous to using the ampersand
(<TT><FONT FACE="Courier">&</FONT></TT>) operator in C to
pass the address of an operator. This method is usually used to
create a second, new reference to the variable in question. Here's
how to create a reference to a scalar variable:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$variable = 22;<BR>
$pointer = \$variable;<BR>
<BR>
$ice = "jello"<BR>
$iceptr = \$ice;</FONT></TT>
</BLOCKQUOTE>
<P>
Now <TT><FONT FACE="Courier">$pointer</FONT></TT> points to the
location containing the value of <TT><FONT FACE="Courier">$variable</FONT></TT>.
The pointer <TT><FONT FACE="Courier">$iceptr</FONT></TT> points
to <TT><FONT FACE="Courier">jello</FONT></TT>. Even if the original
reference (<TT><FONT FACE="Courier">$variable</FONT></TT>) goes
away, you can still access the value from the <TT><FONT FACE="Courier">$pointer</FONT></TT>
reference. It's a hard reference at work here, so you have to
get rid of both <TT><FONT FACE="Courier">$pointer</FONT></TT>
and <TT><FONT FACE="Courier">$variable</FONT></TT> to free up
the space in which the value of <TT><FONT FACE="Courier">jello</FONT></TT>
is allocated. Similarly, <TT><FONT FACE="Courier">$variable</FONT></TT>
contains the number <TT><FONT FACE="Courier">22</FONT></TT> and
because <TT><FONT FACE="Courier">$pointer</FONT></TT> refers to
<TT><FONT FACE="Courier">$variable</FONT></TT>, dereferencing
the <TT><FONT FACE="Courier">$pointer</FONT></TT> with the statement
<TT><FONT FACE="Courier">$$pointer</FONT></TT> returns a value
of <TT><FONT FACE="Courier">22</FONT></TT>. In a subroutine, both
<TT><FONT FACE="Courier">$variable</FONT></TT> and <TT><FONT FACE="Courier">$pointer</FONT></TT>
have to be declared as "local" or "my" variables.
If they are both not declared as such, at least one of these variables
will persist as a global variable long after the subroutine in
which they are declared returns. As long as either of these variables
exists, the space for storing the numbers will also exist.
<P>
The variable <TT><FONT FACE="Courier">$pointer</FONT></TT> contains
the address of the <TT><FONT FACE="Courier">$variable</FONT></TT>,
not the value itself. To get the value, you have to dereference
<TT><FONT FACE="Courier">$pointer</FONT></TT> with <I>two </I>dollar
signs,<I> </I><TT><FONT FACE="Courier">$$</FONT></TT>. Listing
3.1 illustrates how this works.
<HR>
<BLOCKQUOTE>
<B>Listing 3.1. References to scalars.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier">1 #!/usr/bin/perl<BR>
2 <BR>
3 $value = 10;<BR>
4 <BR>
5 $pointer = \$value;<BR>
6 <BR>
7 printf "\n Pointer Address $pointer of $value
\n";<BR>
8 <BR>
9 printf "\n What Pointer *($pointer) points to $$pointer\n";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
<TT><FONT FACE="Courier">$value</FONT></TT> in this script is
set to <TT><FONT FACE="Courier">10</FONT></TT>. <TT><FONT FACE="Courier">$pointer</FONT></TT>
is set to point to the address of <TT><FONT FACE="Courier">$value</FONT></TT>.
The two <TT><FONT FACE="Courier">printf</FONT></TT> statements
show how the value of the variable is being referenced. If you
run this script, you'll see something very close to this output:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Pointer Address SCALAR(0x806c520) of
10<BR>
<BR>
What Pointer *(SCALAR(0x806c520)) points to 10</FONT></TT>
</BLOCKQUOTE>
<P>
The address shown in the output from your script definitely will
be different from the one shown here. However, you can see that
<TT><FONT FACE="Courier">$pointer</FONT></TT> gave the address,
and <TT><FONT FACE="Courier">$$pointer</FONT></TT> gave the value
of the scalar pointed to by <TT><FONT FACE="Courier">$variable</FONT></TT>.
<P>
The word <TT><FONT FACE="Courier">SCALAR</FONT></TT> followed
by a long hexadecimal number in the address value tells you that
the address points to a scalar variable. The number following
<TT><FONT FACE="Courier">SCALAR</FONT></TT> is the address where
the information of the scalar variable is being kept.
<H2><A NAME="ReferencesandArrays"><FONT SIZE=5 COLOR=#FF0000>References
and Arrays</FONT></A></H2>
<P>
This is perhaps the most important thing you must remember about
Perl: all Perl <TT><FONT FACE="Courier">@ARRAY</FONT></TT>s and
<TT><FONT FACE="Courier">%HASH</FONT></TT>es are always one-dimensional.
As such, the arrays and hashes hold only scalar values and do
not directly contain other arrays or complex data structures.
If it's a member of an array, it's either a data item or a reference
to a data item.
<P>
You can also use the backslash operator on arrays and hashes,
just as you would for scalar variables. For arrays, you use something
like the Perl script in Listing 3.2.
<HR>
<BLOCKQUOTE>
<B>Listing 3.2. Using array references.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -