C++编程思想 答案 第十一章 其他章节点击用户名找 thinking in C++ annotated solution guidecharpter 11Word文件下载.docx
《C++编程思想 答案 第十一章 其他章节点击用户名找 thinking in C++ annotated solution guidecharpter 11Word文件下载.docx》由会员分享,可在线阅读,更多相关《C++编程思想 答案 第十一章 其他章节点击用户名找 thinking in C++ annotated solution guidecharpter 11Word文件下载.docx(20页珍藏版)》请在冰点文库上搜索。
Writeaprograminwhichyoutryto
(1)Createareferencethatisnotinitializedwhenitiscreated.
(2)Changeareferencetorefertoanotherobjectafteritisinitialized.(3)CreateaNULLreference.
11-4
Writeafunctionthattakesapointerargument,modifieswhatthepointerpointsto,andthenreturnsthedestinationofthepointerasareference.
11-5
Createaclasswithsomememberfunctions,andmakethattheobjectthatispointedtobytheargumentofExercise4.Makethepointeraconstandmakesomeofthememberfunctionsconstandprovethatyoucanonlycalltheconstmemberfunctionsinsideyourfunction.Maketheargumenttoyourfunctionareferenceinsteadofapointer.
11-6
Takethecodefragmentsatthebeginningofthesectiontitled“Pointerreferences”andturnthemintoaprogram.
11-7
Createafunctionthattakesanargumentofareferencetoapointertoapointerandmodifiesthatargument.Inmain(),callthefunction.
11-8
Createafunctionthattakesachar&
argumentandmodifiesthatargument.Inmain(),printoutacharvariable,callyourfunctionforthatvariable,andprintitoutagaintoprovetoyourselfthatithasbeenchanged.Howdoesthisaffectprogramreadability?
Solution:
//:
S11:
CallByRef.cpp
#include<
iostream>
voidnextc(char&
c){
staticcharletter='
a'
;
c=letter++;
}
intmain(){
usingnamespacestd;
charc='
z'
cout<
<
"
c=="
<
c<
endl;
nextc(c);
/*Output:
c==z
c==a
c==b
*/
///:
~
ACprogrammerwillfinditverystrangeindeedthatcischangedinmain(),sinceapointerwasn’tpassed.Pass-by-referencesemanticshavesideeffectsandshouldbeusedsparingly.Agoodexampleisistream:
:
get(char&
c).Sincestreamfunctionsreturnareferencetothestreamitselfsoyoucanimmediatelytestitforend-of-file,thecharacterextractedfromtheinputstreamisstoredviathereferenceargumentc.
11-9
Writeaclassthathasaconstmemberfunctionandanon-constmemberfunction.Writethreefunctionsthattakeanobjectofthatclassasanargument;
thefirsttakesitbyvalue,thesecondbyreference,andthethirdbyconstreference.Insidethefunctions,trytocallbothmemberfunctionsofyourclassandexplaintheresults.
11-10
(Somewhatchallenging)Writeasimplefunctionthattakesanintasanargument,incrementsthevalue,andreturnsit.Inmain(),callyourfunction.Nowdiscoverhowyourcompilergeneratesassemblycodeandtracethroughtheassemblystatementssothatyouunderstandhowargumentsarepassedandreturned,andhowlocalvariablesareindexedoffthestack.
11-11
Writeafunctionthattakesasitsargumentsachar,int,float,anddouble.Generateassemblycodewithyourcompilerandfindthestatementsthatpushtheargumentsonthestackbeforeafunctioncall.
11-12
Writeafunctionthatreturnsadouble.Generateassemblycodeanddeterminehowthevalueisreturned.
11-13
ProduceassemblycodeforPassingBigStructures.cpp.Tracethroughanddemystifythewayyourcompilergeneratescodetopassandreturnlargestructures.
11-14
Writeasimplerecursivefunctionthatdecrementsitsargumentandreturnszeroiftheargumentbecomeszero,otherwiseitcallsitself.Generateassemblycodeforthisfunctionandexplainhowthewaythattheassemblycodeiscreatedbythecompilersupportsrecursion.
11-15
Writecodetoprovethatthecompilerautomaticallysynthesizesacopy-constructorifyoudon’tcreateoneyourself.Provethatthesynthesizedcopy-constructorperformsabitcopyofprimitivetypesandcallsthecopy-constructorofuser-definedtypes.
AutoCopy.cpp
usingnamespacestd;
classInner{
doublex;
public:
Inner(doublex){
this->
x=x;
}
Inner(constInner&
i2){
x=i2.x;
Inner:
Inner(constInner&
)\n"
doublegetX()const{
returnx;
};
classOuter{
Innerm;
intn;
Outer(doublex,inti):
m(x),n(i){}
voidprint(){
'
('
m.getX()<
'
n<
Outero1(10.0,20);
o1.print();
Outero2(o1);
o2.print();
(10,20)
)
ClassOutercontainsaninstanceofclassInnerandanint,butithasnocopyconstructor,sothecompilerwillbuildoneforus.ClassInnerhasacopyconstructorthatannouncesitselfsoyoucanseethatitexecutes,andthesubsequentcalltoOuter:
print()alsorevealsthattheintmemberwascopiedcorrectly.
11-16
Writeaclasswithacopy-constructorthatannouncesitselftocout.Nowcreateafunctionthatpassesanobjectofyournewclassinbyvalueandanotheronethatcreatesalocalobjectofyournewclassandreturnsitbyvalue.Callthesefunctionstoprovetoyourselfthatthecopy-constructorisindeedquietlycalledwhenpassingandreturningobjectsbyvalue.
TraceCopies.cpp
classTrace{
Trace(intn){
Trace:
Trace("
n=n;
Trace(constTrace&
t){
Trace(constTrace&
n=t.n;
intgetN()const{
returnn;
voidf(Tracet){
f("
t.getN()<
Traceg(){
Tracet
(2);
returnt;
Traceh(intn){
Tracet1=1;
f(t1);
Tracet2=g();
Tracet3=h(3);
*CompilerA:
Trace
(1)
f
(1)
Trace
(2)
Trace(3)
*CompilerB:
Simplydefineacopyconstructorthatannouncesitself.Rememberthatifyoudefineanyconstructoratall(includingacopyconstructor),thecompilerwillnotsynthesizeadefaultconstructorforyou,soIneededtodefinesomeconstructorotherthanthecopyconstructorsoIcancreateTraceobjects.IchosetotakeanintargumentsoIcanbettertracethroughthehiddenoperations.
CompilerAperformsnooptimizationssoyoucanseeallthepossibleoperations.Thefirstlineisthecreationoft1,andthenexttwoarethecallthatpassest1tof().Thecalltog()invokestwocallstothecopyconstructor:
onetocreatethereturnvalue,andanothertoinitializet2withthatvalue.Noticethath()returnsaTraceobjectbyvalue,butinsteadofusingthecopyconstructoritusesthesingle-argconstructorthattakesanint.That’sbecausewe’reaskingthecompilertocreateaTraceobjectfromanint.Thebottomlineis,wheneveranobjectiscreated,someconstructoriscalled;
whichonedependsonthecontext.
CompilerBisalotsmarterthanCompilerAwhenitcomestocreatingcopies.
11-17
Createaclassthatcontainsadouble*.Theconstructorinitializesthedouble*bycallingnewdoubleandassigningavaluetotheresultingstoragefromtheconstructorargument.Thedestructorprintsthevaluethat’spointedto,assignsthatvalueto-1,callsdeleteforthestorage,andthensetsthepointertozero.Nowcreateafunctionthattakesanobjectofyourclassbyvalue,andcallthisfunctioninmain().Whathappens?
Fixtheproblembywritingacopy-constructor.
ShallowCopy.cpp
classHasPointer{
double*p;
HasPointer(doublex){
p=newdouble(x);
~HasPointer(){
~HasPointer()\n"
deletep;
*p<
voidf(HasPointerhp)
{
hp.print();
HasPointerhp(5);
f(hp);
5
~HasPointer()
accessviolationerror...!
!
>
(Asasidenote,noticethatyoucanuseconstructorsyntaxtoinitializebuilt-intypesinnewexpressions,asintheconstructorforHasPointer.)
Whenyoucallf(hp),acopyofhpispassedtof(),thedestructorofwhichexecuteswhenthatcopyisnolongerneeded.Problemis,thedestructordeletesp,sowhenthedestructorrunsagaintodestroyhpasmain()completes,ittriestodeletepasecondtime!
ThesolutionistohavethecompilerperformadeepcopyofHasPointerobjectsviaanappropriatecopyconstructor,suchas:
HasPointer(constHasPointer&
rhs){
p=newdouble(*rhs.p);
Asarule,aclasswithapointermemberprobablyneedsacopyconstructor(andasyou’llseeinthenextchapter,anappropriateassignmentoperatortoo).
11-18
Createaclasswithaconstructorthatlookslikeacopy-construct