📄 ch11_01.htm
字号:
<HTML><HEAD><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:40:22Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="index.htm"TITLE="Perl Cookbook"><LINKREL="prev"HREF="ch10_18.htm"TITLE="10.17. Program: Sorting Your Mail"><LINKREL="next"HREF="ch11_02.htm"TITLE="11.1. Taking References to Arrays"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch10_18.htm"TITLE="10.17. Program: Sorting Your Mail"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 10.17. Program: Sorting Your Mail"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch11_02.htm"TITLE="11.1. Taking References to Arrays"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 11.1. Taking References to Arrays"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="chapter"><H1CLASS="chapter"><ACLASS="title"NAME="ch11-17513">11. References and Records</A></H1><DIVCLASS="htmltoc"><P><B>Contents:</B><BR><ACLASS="sect1"HREF="#ch11-31765"TITLE="11.0. Introduction">Introduction</A><BR><ACLASS="sect1"HREF="ch11_02.htm"TITLE="11.1. Taking References to Arrays">Taking References to Arrays</A><BR><ACLASS="sect1"HREF="ch11_03.htm"TITLE="11.2. Making Hashes of Arrays">Making Hashes of Arrays</A><BR><ACLASS="sect1"HREF="ch11_04.htm"TITLE="11.3. Taking References to Hashes">Taking References to Hashes</A><BR><ACLASS="sect1"HREF="ch11_05.htm"TITLE="11.4. Taking References to Functions">Taking References to Functions</A><BR><ACLASS="sect1"HREF="ch11_06.htm"TITLE="11.5. Taking References to Scalars">Taking References to Scalars</A><BR><ACLASS="sect1"HREF="ch11_07.htm"TITLE="11.6. Creating Arrays of Scalar References">Creating Arrays of Scalar References</A><BR><ACLASS="sect1"HREF="ch11_08.htm"TITLE="11.7. Using Closures Instead of Objects">Using Closures Instead of Objects</A><BR><ACLASS="sect1"HREF="ch11_09.htm"TITLE="11.8. Creating References to Methods">Creating References to Methods</A><BR><ACLASS="sect1"HREF="ch11_10.htm"TITLE="11.9. Constructing Records">Constructing Records</A><BR><ACLASS="sect1"HREF="ch11_11.htm"TITLE="11.10. Reading and Writing Hash Records to Text Files">Reading and Writing Hash Records to Text Files</A><BR><ACLASS="sect1"HREF="ch11_12.htm"TITLE="11.11. Printing Data Structures">Printing Data Structures</A><BR><ACLASS="sect1"HREF="ch11_13.htm"TITLE="11.12. Copying Data Structures">Copying Data Structures</A><BR><ACLASS="sect1"HREF="ch11_14.htm"TITLE="11.13. Storing Data Structures to Disk">Storing Data Structures to Disk</A><BR><ACLASS="sect1"HREF="ch11_15.htm"TITLE="11.14. Transparently Persistent Data Structures">Transparently Persistent Data Structures</A><BR><ACLASS="sect1"HREF="ch11_16.htm"TITLE="11.15. Program: Binary Trees">Program: Binary Trees</A></P><P></P></DIV><DIVCLASS="epigraph"ALIGN="right"><PCLASS="para"ALIGN="right"><I>With as little a web as this will I ensnare as great a fly as Cassio.</I></P><PCLASS="attribution"ALIGN="right">- Shakespeare <CITECLASS="citetitle">Othello, Act II, scene i </CITE></P></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch11-31765">11.0. Introduction</A></H2><PCLASS="para">Perl provides three fundamental data types: scalars, arrays, and hashes. It's certainly possible to write many programs without recourse to complex records, but most programs need something more complex than simple variables and lists.</P><PCLASS="para">Perl's three built-in types combine with references to produce arbitrarily complex and powerful data structures, the records that users of ancient versions of Perl desperately yearned for. Selecting the proper data structure and algorithm can make the difference between an elegant program that does its job quickly and an ungainly concoction that's glacially slow to execute and consumes system resources voraciously.</P><PCLASS="para">The first part of this chapter shows how to create and use plain references. The second part shows how to use references to create higher order data structures.</P><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-chap11_references_1">References</A></H3><PCLASS="para"><ACLASS="indexterm"NAME="ch11-idx-1000004778-0"></A>To grasp the concept of references, you must first understand how Perl stores values in variables. Each defined variable has a name and the address of a chunk of memory associated with it. This idea of storing addresses is fundamental to references because a reference is a value that holds the location of another value. The scalar value that contains the memory address is called a <EMCLASS="emphasis">reference</EM>. Whatever value lives at that memory address is called a <EMCLASS="emphasis">referent</EM><ACLASS="indexterm"NAME="ch11-idx-1000004785-0"></A>. (You may also call it a "thingie" if you prefer to live a whimsical existence.) See <ACLASS="xref"HREF="ch11_01.htm#ch11-12670"TITLE="Reference and referent">Figure 11.1</A>.</P><PCLASS="para">The referent could be any of Perl's built-in types (scalar, array, hash, ref, code, or glob) or a user-defined type based on one of the built-in ones.</P><H4CLASS="figure"><ACLASS="title"NAME="ch11-12670">Figure 11.1: Reference and referent</A></H4><IMGCLASS="graphic"SRC="figs/pcb_1101.gif"ALT="Figure 11.1"><PCLASS="para">Referents in Perl are <EMCLASS="emphasis">typed</EM><ACLASS="indexterm"NAME="ch11-idx-1000004784-0"></A>. This means you can't treat a reference to an array as though it were a reference to a hash, for example. Attempting to do so produces a runtime exception. No mechanism for type casting exists in Perl. This is considered a feature.</P><PCLASS="para">So far, it may look as though a reference were little more than a raw address with strong typing. But it's far more than that. Perl takes care of automatic memory allocation and deallocation (garbage collection) for references, just as it does for everything else. Every chunk of memory in Perl has a <EMCLASS="emphasis">reference count</EM><ACLASS="indexterm"NAME="ch11-idx-1000004786-0"></A> associated with it, representing how many places know about that referent. The memory used by a referent is not returned to the process's free pool until its reference count reaches zero. This ensures that you never have a reference that isn't valid - no more core dumps and general protection faults from mismanaged pointers as in C.</P><PCLASS="para">Freed memory is returned to Perl for later use, but few operating systems reclaim it and decrease the process's memory footprint. This is because most memory allocators use a stack, and if you free up memory in the middle of the stack, the operating system can't take it back without moving the rest of the allocated memory around. That would destroy the integrity of your pointers and blow XS code out of the water.</P><PCLASS="para">To follow a reference to its referent, preface the reference with the appropriate type symbol for the data you're accessing. For instance, if <CODECLASS="literal">$sref</CODE> is a reference to a scalar, you can say:</P><PRECLASS="programlisting">print $$sref; # prints the scalar value that the reference $sref refers to$$sref = 3; # assigns to $sref's referent</PRE><PCLASS="para">To access one element of an array or hash whose reference you have, use the <ACLASS="indexterm"NAME="ch11-idx-1000004787-0"></A><ACLASS="indexterm"NAME="ch11-idx-1000004787-1"></A><ACLASS="indexterm"NAME="ch11-idx-1000004787-2"></A>infix pointer-arrow notation, as in <CODECLASS="literal">$rv->[37]</CODE> or <CODECLASS="literal">$rv->{"wilma"}</CODE>. Besides dereferencing array references and hash references, the arrow is also used to call an indirect function through its reference, as in <CODECLASS="literal">$code_ref->("arg1",</CODE> <CODECLASS="literal">"arg2")</CODE>; this is discussed <ACLASS="xref"HREF="ch11_05.htm"TITLE="Taking References to Functions">Recipe 11.4</A>. If you're using an object, use an arrow to call a method, <CODECLASS="literal">$object->methodname("arg1",</CODE><SPANCLASS="acronym"> </SPAN><CODECLASS="literal">"arg2")</CODE>, as shown in <ACLASS="xref"HREF="ch13_01.htm"TITLE="Classes, Objects, and Ties">Chapter 13, <CITECLASS="chapter">Classes, Objects, and Ties</CITE></A>.</P><PCLASS="para">Perl's syntax rules make dereferencing complex expressions tricky - it falls into the category of "hard things that should be possible." Mixing right associative and left associative operators doesn't work out well. For example, <CODECLASS="literal">$$x[4]</CODE> is the same as <CODECLASS="literal">$x->[4]</CODE>; that is, it treats <CODECLASS="literal">$x</CODE> as a reference to an array and then extracts element number four from that. This could also have been written <CODECLASS="literal">${$x}[4]</CODE>. If you really meant "take the fifth element of <CODECLASS="literal">@x</CODE> and dereference it as a scalar reference," then you need to use <CODECLASS="literal">${$x[4]}</CODE>. You should avoid putting two type signs (<CODECLASS="literal">$@%&</CODE>) side-by-side, unless it's simple and unambiguous like <CODECLASS="literal">%hash</CODE> <CODECLASS="literal">=</CODE> <CODECLASS="literal">%$hashref</CODE>.</P><PCLASS="para">In the simple cases using <CODECLASS="literal">$$sref</CODE> above, you could have written:</P><PRECLASS="programlisting">print ${$sref}; # prints the scalar $sref refers to${$sref} = 3; # assigns to $sref's referent</PRE><PCLASS="para">For safety, some programmers use this notation exclusively.</P><PCLASS="para">When passed a reference, the <CODECLASS="literal">ref</CODE><ACLASS="indexterm"NAME="ch11-idx-1000004788-0"></A> function returns a string describing its referent. (It returns false if passed a non-reference.) This string is usually one of SCALAR, ARRAY, HASH, or CODE, although the other built-in types of GLOB, REF, IO, Regexp, and LVALUE also occasionally appear. If you call <CODECLASS="literal">ref</CODE> on a non-reference, it returns an empty string. If you call <CODECLASS="literal">ref</CODE> on an object (a reference whose referent has been blessed), it returns the class the object was blessed into: CGI, IO::Socket, or even ACME::Widget.</P><PCLASS="para">You can create references in Perl by taking references to things that are already there or by using the <CODECLASS="literal">[</CODE> <CODECLASS="literal">]</CODE>, <CODECLASS="literal">{</CODE> <CODECLASS="literal">}</CODE>, and <CODECLASS="literal">sub</CODE> <CODECLASS="literal">{</CODE> <CODECLASS="literal">}</CODE> composers. The backslash operator is simple to use: put it before the thing you want a reference to. For instance, if you want a reference to the contents of <CODECLASS="literal">@array</CODE>, just say:</P><PRECLASS="programlisting">$aref = \@array;</PRE><PCLASS="para">You can even create references to constant values; future attempts to change the value of the referent will cause a runtime error:</P><PRECLASS="programlisting">$pi = \3.14159;$$pi = 4; # runtime error<ACLASS="indexterm"NAME="ch11-idx-1000004779-0"></A></PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch11-chap11_anonymous_0">Anonymous Data</A></H3><PCLASS="para"><ACLASS="indexterm"NAME="ch11-idx-1000004780-0"></A>Taking references to existing data is helpful when you're using pass-by-reference in a function call, but for dynamic programming, it becomes cumbersome. You need to be able to grow data structures at will, to allocate new arrays and hashes (or scalars or functions) on demand. You don't want to be bogged down with having to give them names each time.</P><PCLASS="para"><ACLASS="indexterm"NAME="ch11-idx-1000004789-0"></A><ACLASS="indexterm"NAME="ch11-idx-1000004789-1"></A>Perl can explicitly create anonymous arrays and hashes, which allocate a new array or hash and return a reference to that memory:</P><PRECLASS="programlisting">$aref = [ 3, 4, 5 ]; # new anonymous array$href = { "How" => "Now", "Brown" => "Cow" }; # new anonymous hash</PRE><PCLASS="para">Perl can also create a reference implicitly by <EMCLASS="emphasis">autovivification</EM><ACLASS="indexterm"NAME="ch11-idx-1000004790-0"></A><ACLASS="indexterm"NAME="ch11-idx-1000004790-1"></A>. This is what happens when you try to assign through an undefined references and Perl automatically creates the reference you're trying to use.</P><PRECLASS="programlisting">undef $aref;@$aref = (1, 2, 3);print $aref;<CODECLASS="userinput"><B><CODECLASS="replaceable"><I>ARRAY(0x80c04f0)</I></CODE></B></CODE></PRE><PCLASS="para">Notice how we went from an undefined variable to one with an array reference in it without actually assigning anything? Perl filled in the undefined reference for you. This is the property that permits something like this to work as the first statement in your program:</P><PRECLASS="programlisting">$a[4][23][53][21] = "fred";print $a[4][23][53][21];<CODECLASS="userinput"><B><CODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -