📄 mi4.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML LANG="EN">
<HEAD>
<TITLE>More Effective C++ | Item 4: Avoid gratuitous default constructors</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">
var dingbase = "MI4_DIR.HTM";
var dingtext = "Item M4, P";
if (self == top) {
top.location.replace(dingbase + this.location.hash);
}</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName="M4: Avoid gratuitous default constructors" -->
<A NAME="5218"></A>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MI3_FR.HTM" TARGET="_top">Item 3: Never treat arrays polymorphically</A> <BR> Continue to <A HREF="./MOPER_FR.HTM" TARGET="_top">Operators</A></FONT></DIV>
<P><A NAME="dingp1"></A><font ID="mititle">Item 4: Avoid gratuitous default constructors.</font><SCRIPT>create_link(1);</SCRIPT>
</P>
<A NAME="72108"></A>
<A NAME="39909"></A>
<P><A NAME="dingp2"></A>
A default constructor (i.e., a constructor that can be called with no arguments) is the C++ way of saying you can get something for nothing. Constructors initialize objects, so default constructors initialize objects without any information from the place where the object is being created. Sometimes this makes perfect sense. Objects that act like numbers, for example, may reasonably be initialized to zero or to undefined values. Objects that act like pointers (
<a href="./MI28_FR.HTM#61766" TARGET="_top">Item 28</A>) may reasonably be initialized to null or to undefined values. Data structures like linked lists, hash tables, maps, and the like may reasonably be initialized to empty <NOBR>containers.<SCRIPT>create_link(2);</SCRIPT>
</NOBR></p><A NAME="39967"></A>
<P><A NAME="dingp3"></A>
Not all objects fall into this category. For many objects, there is no reasonable way to perform a complete initialization in the absence of outside information. For example, an object representing an entry in an address book makes no sense unless the name of the thing being entered is provided. In some companies, all equipment must be tagged with a corporate ID number, and creating an object to model a piece of equipment in such companies is nonsensical unless the appropriate ID number is <NOBR>provided.<SCRIPT>create_link(3);</SCRIPT>
</NOBR></p><A NAME="39989"></A>
<P><A NAME="dingp4"></A>
In a perfect world, classes in which objects could reasonably be created from nothing would contain default constructors and classes in which information was required for object construction would not. Alas, ours is not the best of all possible worlds, so we must take additional concerns into account. In particular, if a class lacks a default constructor, there are restrictions on how you can use that <NOBR>class.<SCRIPT>create_link(4);</SCRIPT>
</NOBR></p><A NAME="40014"></A>
<P><A NAME="dingp5"></A>
Consider a class for company equipment in which the corporate ID number of the equipment is a mandatory constructor <NOBR>argument:<SCRIPT>create_link(5);</SCRIPT>
</NOBR></p><A NAME="40028"></A>
<UL><PRE>class EquipmentPiece {
public:
EquipmentPiece(int IDNumber);
...
};</PRE>
</UL>
<A NAME="40047"></A>
<P><A NAME="dingp6"></A>
Because <CODE>EquipmentPiece</CODE> lacks a default constructor, its use may be problematic in three contexts. The first is the creation of arrays. There <A NAME="p20"></A>is, in general, no way to specify constructor arguments for objects in arrays, so it is not usually possible to create arrays of <CODE>EquipmentPiece</CODE> <NOBR>objects:<SCRIPT>create_link(6);</SCRIPT>
</NOBR></P>
<A NAME="40048"></A>
<UL><PRE>
EquipmentPiece bestPieces[10]; // error! No way to call
// EquipmentPiece ctors
<A NAME="65521"></A>
EquipmentPiece *bestPieces =
new EquipmentPiece[10]; // error! same problem</PRE>
</UL>
<A NAME="65538"></A>
<P><A NAME="dingp7"></A>
There are three ways to get around this restriction. A solution for non-heap arrays is to provide the necessary arguments at the point where the array is <NOBR>defined:<SCRIPT>create_link(7);</SCRIPT>
</NOBR></P>
<A NAME="65511"></A>
<UL><PRE>
int ID1, ID2, ID3, ..., ID10; // variables to hold
// equipment ID numbers
...
<A NAME="65514"></A>
EquipmentPiece bestPieces[] = { // fine, ctor arguments
EquipmentPiece(ID1), // are provided
EquipmentPiece(ID2),
EquipmentPiece(ID3),
...,
EquipmentPiece(ID10)
};</PRE>
</UL>
<A NAME="65508"></A>
<P><A NAME="dingp8"></A>
Unfortunately, there is no way to extend this strategy to heap <NOBR>arrays.<SCRIPT>create_link(8);</SCRIPT>
</NOBR></p><A NAME="65509"></A>
<P><A NAME="dingp9"></A>
A more general approach is to use an array of <I>pointers</I> instead of an array of <NOBR>objects:<SCRIPT>create_link(9);</SCRIPT>
</NOBR></p><A NAME="40054"></A>
<UL><PRE>typedef EquipmentPiece* PEP; // a PEP is a pointer to
// an EquipmentPiece
<A NAME="65548"></A>
PEP bestPieces[10]; // fine, no ctors called
</PRE>
</UL><A NAME="65552"></A>
<UL><PRE>PEP *bestPieces = new PEP[10]; // also fine
</PRE>
</UL><A NAME="40058"></A>
<P><A NAME="dingp10"></A>
Each pointer in the array can then be made to point to a different <CODE>EquipmentPiece</CODE> <NOBR>object:<SCRIPT>create_link(10);</SCRIPT>
</NOBR></p><A NAME="40057"></A>
<UL><PRE>for (int i = 0; i < 10; ++i)
bestPieces[i] = new EquipmentPiece( <I>ID Number</I> );
</PRE>
</UL><A NAME="40062"></A>
<P><A NAME="dingp11"></A>
There are two disadvantages to this approach. First, you have to remember to delete all the objects pointed to by the array. If you forget, you have a resource leak. Second, the total amount of memory you need increases, because you need the space for the pointers as well as the space for the <CODE>EquipmentPiece</CODE> <NOBR>objects.<SCRIPT>create_link(11);</SCRIPT>
</NOBR></p><A NAME="40052"></A>
<P><A NAME="dingp12"></A>
You can avoid the space penalty if you allocate the raw memory for the array, then use "placement <CODE>new</CODE>" (see <a href="./MI8_FR.HTM#33985" TARGET="_top">Item 8</A>) to construct the <CODE>EquipmentPiece</CODE> objects in the <NOBR>memory:<SCRIPT>create_link(12);</SCRIPT>
</NOBR></p><A NAME="40083"></A>
<UL><PRE><A NAME="p21"></A>// allocate enough raw memory for an array of 10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -