C++编程思想答案第十三章其他章节点击用户名找thinkinginC++annotatedsolutionguide(charpter13).doc_第1页
C++编程思想答案第十三章其他章节点击用户名找thinkinginC++annotatedsolutionguide(charpter13).doc_第2页
C++编程思想答案第十三章其他章节点击用户名找thinkinginC++annotatedsolutionguide(charpter13).doc_第3页
C++编程思想答案第十三章其他章节点击用户名找thinkinginC++annotatedsolutionguide(charpter13).doc_第4页
C++编程思想答案第十三章其他章节点击用户名找thinkinginC++annotatedsolutionguide(charpter13).doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Viewing Hints Book Home Page Free Newsletter Seminars Seminars on CD ROM Consulting Annotated Solution GuideRevision 1.0for Thinking in C+, 2nd edition, Volume 1by Chuck Allison2001 MindView, Inc. All Rights Reserved. Previous Chapter Table of Contents Next Chapter Chapter 1313-1Create a class Counted that contains an int id and a static int count. The default constructor should begin: Counted( ) : id(count+) . It should print its id and that its being created. The destructor should print that its being destroyed and its id. Test your class.(Left to the reader)13-2Prove to yourself that new and delete always call the constructors and destructors by creating an object of class Counted(from Exercise 1) with new and destroying it with delete. Also create and destroy an array of these objects on the heap.Solution:/: S13:Counted.cpp#include using namespace std;class Counted int id; static int count;public: Counted() : id(count+) cout Creating Counted( id )n; Counted() cout Destroying Counted( id )n; ;int Counted:count = 0;int main() Counted* c = new Counted; delete c; Counted * const a = new Counted3; delete a;/* Output:Creating Counted(0)Destroying Counted(0)Creating Counted(1)Creating Counted(2)Creating Counted(3)Destroying Counted(3)Destroying Counted(2)Destroying Counted(1)*/:Just for fun I followed Bruces advice and declared a to be a const pointer above (I usually forget). Remember to use the delete operator when freeing an array.13-3Repeat Exercise 4, but add a member function f( ) to Counted that prints a message. Move through the vector and call f( ) for each object.13-4Repeat Exercise 5 using a PStash.13-5Repeat Exercise 4, but add a member function f( ) to Counted that prints a message. Move through the vector and call f( ) for each object.Solution:/: S13:CountedVector.cpp#include #include #include / For size_tusing namespace std;class Counted int id; static int count;public: Counted() : id(count+) cout Creating Counted( id )n; Counted() cout Destroying Counted( id )n; void f() cout Hi! Im # id endl; ;int Counted:count = 0;int main() vector v; for (size_t i = 0; i 3; +i) v.push_back(new Counted); for (size_t i = 0; i f(); for (size_t i = 0; i v.size(); +i) delete vi;/* Output:Creating Counted(0)Creating Counted(1)Creating Counted(2)Hi! Im #0Hi! Im #1Hi! Im #2Destroying Counted(0)Destroying Counted(1)Destroying Counted(2)*/:I use size_t for i above because thats what vector:size( ) returns, and I didnt want any signed-to-unsigned comparison warnings from my compiler. In Volume 2 youll see better ways of applying a function to elements in a container.13-6Dynamically create an array of objects of class Counted(from Exercise 1). Call delete for the resulting pointer, without the square brackets. Explain the results.13-7Create an object of class Counted(from Exercise 1) using new, cast the resulting pointer to a void*, and delete that. Explain the results.13-8Dynamically create an array of objects of class Counted(from Exercise 1). Call delete for the resulting pointer, without the square brackets. Explain the results.Solution:/: S13:WrongDelete.cpp#include #include using namespace std;class Counted int id; static int count;public: Counted() : id(count+) cout Creating Counted( id )n; Counted() cout Destroying Counted( id )n; void f() cout Hi! Im # id endl; ;int Counted:count = 0;int main() Counted *const a = new Counted3; delete a;/* Output:Creating Counted(0)Creating Counted(1)Creating Counted(2)Destroying Counted(0)*/:Another compiler caused my machine to hang when I ran this program! If a was created as an array, it must be deleted as an array, since more work needs to be done than just destroying a single element. Each compiler can do this however it wants; you just need to be sure that whenever you use brackets in the new operation, you must also use delete to destroy the objects. There are even different library functions called to free scalar memory (operator delete( ) vs. array memory (operator delete( ), and you override them separately.13-9Create an object of class Counted(from Exercise 1) using new, cast the resulting pointer to a void*, and delete that. Explain the results.Solution:/: S13:WrongPointer.cpp#include #include using namespace std;class Counted int id; static int count;public: Counted() : id(count+) cout Creating Counted( id )n; Counted() cout Destroying Counted( id )n; void f() cout Hi! Im # id endl; ;int Counted:count = 0;int main() Counted* c = new Counted; void* p = c; delete p;/* Output:Creating Counted(0)*/:I chose to define a void* variable in a separate step instead of casting the new expression, but the results are the same: when you delete a void*, no destructor is called, which is almost always bad news.13-10Devise a test for Framis.cpp to show yourself approximately how much faster the custom new and delete run than the global new and delete.13-11Create a class with an overloaded operator new and delete, both the single-object versions and the array versions. Demonstrate that both versions work.Solution:/: S13:ClassHeap.cpp#include #include #include / For size_tusing namespace std;class OwnHeap public: OwnHeap() printf(OwnHeap:OwnHeap()n); OwnHeap() printf(OwnHeap:OwnHeap()n); static void* operator new(size_t) throw(bad_alloc); static void operator delete(void*, size_t); static void* operator new(size_t sz) throw(bad_alloc); static void operator delete(void* p, size_t);void* OwnHeap:operator new(size_t size) throw(bad_alloc) for (;) void* block = :operator new(size); if (block) printf(OwnHeap:operator new() allocating %lu bytes in %pn, static_cast(size), block); return block; new_handler globalHandler = set_new_handler(0); set_new_handler(globalHandler); if (globalHandler) globalHandler(); else throw bad_alloc(); void OwnHeap:operator delete(void* p, size_t size) printf(OwnHeap:operator delete freeing %lu bytes in %pn, static_cast(size), p); :operator delete(p);void* OwnHeap:operator new(size_t size) throw(bad_alloc) printf(OwnHeap:operator new() calling OwnHeap:operator new(%lu)n, static_cast(size); return operator new(size);void OwnHeap:operator delete(void* p, size_t size) printf(OwnHeap:operator delete() calling OwnHeap:operator delete(%p, %lu)n, p, static_cast(size); operator delete(p, size);int main() OwnHeap* p = new OwnHeap; OwnHeap* pa = new OwnHeap2; delete p; delete pa;/* Output (yours may vary):OwnHeap:operator new() allocating 1 bytes in 0x804a7e8OwnHeap:OwnHeap()OwnHeap:operator new() calling OwnHeap:operator new(6)OwnHeap:operator new() allocating 6 bytes in 0x804a7f8OwnHeap:OwnHeap()OwnHeap:OwnHeap()OwnHeap:OwnHeap()OwnHeap:operator delete freeing 1 bytes in 0x804a7e8OwnHeap:OwnHeap()OwnHeap:OwnHeap()OwnHeap:operator delete() calling OwnHeap:operator delete(0x804a7f8, 6)OwnHeap:operator delete freeing 6 bytes in 0x804a7f8 */:When you define class-based operator new and delete functions, they are static member functions, whether or not you declare them so, but its good style to be explicit about it. There are quite a number of allocation-related functions defined in the standard C+ library. In fact, here are all the prototypes:void* operator new(std:size_t size) throw(std:bad_alloc);void* operator new(std:size_t size, const std:nothrow_t&) throw();void operator delete(void* ptr) throw();void operator delete(void* ptr, const std:nothrow_t&) throw();void* operator new(std:size_t size) throw(std:bad_alloc);void* operator new(std:size_t size, const std:nothrow_t&) throw();void operator delete(void* ptr) throw();void operator delete(void* ptr, const std:nothrow_t&) throw();void* operator new (std:size_t size, void* ptr) throw();void* operator new(std:size_t size, void* ptr) throw();void operator delete (void* ptr, void*) throw();void operator delete(void* ptr, void*) throw();All except the placement versions that take an extra void* parameter (the last four above) can be overridden either globally or on a class basis. The nothrow versions return a null pointer if memory fails; the others throw a bad_alloc exception. I patterned the implementation of OwnHeap:operator new after the global one, which basically has a loop, and throws a bad_alloc exception if there is no new handler defined (which is the default case). Here is an excerpt from the C+ Standard describing the global operator new:Executes a loop: Within the loop, the function first attempts to allocate the requested storage. Whether the attempt involves a call to the Standard C library function malloc is unspecified.Returns a pointer to the allocated storage if the attempt is successful. Otherwise, if the last argument to set_new_handler() was a null pointer, throw bad_alloc.Otherwise, the function calls the current new_handler. If the called function returns, the loop repeats.The loop terminates when an attempt to allocate the requested storage is successful or when a called new_handler function does not return.The only difference between the above and OwnHeap:operator new is that the latter calls the global operator new to allocate the storage.Note that there are two versions of operator delete: one that takes a second size_t parameter, and one that doesnt. The two-parameter version allows you to capture the number of bytes that are going to be deleted. This is the version that I defined in this solution. Dont be too alarmed if your compiler doesnt delete the same amount of memory that was allocated for the array of OwnHeap objects. Most of the compilers I used didnt. Go figure.Since I didnt have anything unique to do for the array versions, I just had them call the scalar versions to do their work. The important thing is that these functions were called when allocating arrays, so you can provide special processing if you need to.13-12Create a class with a placement new with a second argument of type string. The class should contain a static vectorwhere the second newargument is stored. The placement newshould allocate storage as normal. In main( ), make calls to your placement new with string arguments that describe the calls (you may want to use the preprocessors _FILE_ and _LINE_ macros).13-13Modify ArrayOperatorNew.cpp by adding a static vector that adds each Widget address that is allocated in operator new( ) and removes it when it is released via operator delete( ). (You may need to look up information about vector in your Standard C+ Library documentation or in the 2nd volume of this book, available at the Web site.) Create a second class called MemoryCheckerthat has a destructor that prints out the number of Widget pointers in your vector. Create a program with a single global instance of MemoryChecker and in main( ), dynamically allocate and destroy several objects and arrays of Widget. Show that MemoryChecker reveals memory leaks.13-14Create a class with a placement new with a second argument of type string. The class should contain a static vectorwhere the second new argument is stored. The placement newshould allocate storage as normal. In main( ), make calls to your placement new with string arguments that describe the calls (you may want to use the preprocessors _FILE_ and _LINE_ macros).Solution:/: S13:PlacementNew.cpp#include #include #include #include #include #include / For size_tusing namespace std;class Track static vector allocs;public: static void* operator new(size_t size, const char* file, int line); static void display();vector Track:allocs;void* Track:operator new(size_t size, const char* file, int line) ostringstream os; os file , line line; allocs.push_back(os.str(); return :operator new(size);void Track:display() for (size_t i = 0; i allocs.size(); +i) cout allocsi endl;/ Preprocessor trick:#define new new (_FILE_, _LINE_)int main() Track* t1 = new Track; Track* t2 = new Track; Track* t3 = new Track; Track:display(); delete t3; delete t2; delete t1;/* Output:x14.cpp, line 34x14.cpp, line 35x14.cpp, line 36*/:This is an interesting problem! The class-based Track:operator new( ) is just a wrapper for the global operator new( ), except that it records the file name and line number where the new operation took place in the static vector before returning the space for the object (which in this case will probably be 1 byte, not zero, so every address returned by the new operator will be distinct). I used an ostringstream to build the string but you could use sprintf( ) if you wanted to. Usually you provide operator delete( ) if you provide operator new( ), but since Track:operator new( ) just calls the global one in this case, the global operator delete( ) will do. The preprocessor trick before main( ) is just to save typing. If you still want different versions of new available, then remove the macro and replace the calls to new to use placement syntax, as inTrack* t1 = new (_FILE_, _LINE) Track;Even more interesting is to use a map to associate addresses with the strings. This way you can delete elements from the static container as you use the delete operator on the object. The following example does just that by defining Track:operator delete( ) as a wrapper for :operator delete( )./: S13:MappedMemory.cpp#include #include #include #include #include #include / For size_tusing namespace std;class Track static map allocs;public: static void* operator new(size_t size, const char* file, int line); static void operator delete(void* p); static void display();map Track:allocs;void* Track:operator new(size_t size, const char* file, int line) ostringstream os; os file , line line; void* addr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论