<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數據加載中……

    Using auto_ptr to Handle Memory

    For instance, it is common to write code such as
    void myFunction()
    {
        myClass = new myClass();
        // body of function
        delete myClass;
    }
    
    and this may work. But what if somewhere in the function body an exception gets thrown? Suddenly, the delete code never gets called! What's more, you may never have intended to throw an exception into the function but one of the functions you call may do so, or you may later need to modify your code to do so. In both cases, this is a memory leak waiting to happen.

    On the other hand, by letting the auto_ptr class manage your memory for you, as soon as an exception gets thrown and the auto_ptr you declared has gone out of scope, the memory allocated will automatically be freed. First, let's look at how to use auto_ptr, and then I'll explain the exact mechanics of how this works.

    To take advantage of auto_ptr, you will need to include <memory>. This will give you access to the std namespace, in which resides the templated class auto_ptr<type>. For type, you should put the type you want your pointer to point to. For instance, if you would ordinarily have declared an int*, you should use int for the type. When you actually declare an instance of the templated class, the constructor should take a pointer to the specified type. The object will then take care of managing the memory associated with that pointer. For instance, to create an auto_ptr object that manages the memory of a pointer to an integer, you could use this declaration:
    std::auto_ptr<int> int_memory_manager(new int);
    // Alternately, you could include "using namespace std;" or 
    // "using namespace std::auto_ptr" at the top of your code to avoid having to
    // prefix all declarations with std::auto_ptr
    
    To actually use the pointer stored in the auto_ptr container, you can just treat the auto_ptr object you create as though it were the pointer. For instance, you can dereference it:
    *int_memory_manager = 5;
    
    and if you wanted to access a member function (or variable) of a struct or class, you can simply use the same arrow operator as normal. I'll use a fictitious class calle "myClass" to illustrate this.
    std::auto_ptr<myClass> myClassManager(new myClass);
    myClass->variable = 50;
    
    which sets a field called variable to 50 in the instance of myClass whose pointer is stored in myClassManager.

    The great benefit of all of this is that you simply don't need to worry about calling delete at all! As soon as int_memory_manager goes out of scope, its destructor will be invoked. Its destructor, in turn, will call delete on the pointer. This brings up a subtle point: you must use ato_ptr with memory allocated with new, not malloc, and, moreover, not new[]. Each of these memory allocators must be properly paired: malloc with free, new with delete, and new[] with delete[] (new[] is used to allocate arrays). If they aren't matched correctly, your program may crash.

    The consequence of auto_ptr's always calling delete on the pointer it stores means that you can't store arrays in an auto_ptr. For instance, the following is a mistake:
    std::auto_ptr<int> int_memory_manager(new int[10]);
    
    What happens when int_memory_manager goes out of scope? The program invokes delete on an array, and this is illegal. Some compilers may let you get away with it, but it's not portable. Just don't do it! If you really need to store a collection of items with constant random access times, just use a vector from the Standard Template Library (STL).

    If you just need to retrieve the address of the pointer held in an auto_ptr object, you can use the get method. The following code demonstrates a function that returns a pointer to an integer as stored in an auto_ptr object:
    int* example()
    {
    std::auto_ptr<int> int_memory_manager(new int);
    return int_memory_manager.release(); // we'll see release in more depth below 
    
    Of course, you'd probably be better off simply returning an auto_ptr object in the first place.

    Some Caveats

    While you can assign one auto_ptr object to another, when you do so, the actual assignment results in the transferral of the pointer from one object to the other.

    For instance,
    std::auto_ptr<int> int_memory_manager(new int);
    std::auto_ptr<int> int_memory_manager2;
    cout<<"Contents of first is "<<int_memory_manager.get()<<endl;
    int_memory_manager2 = int_memory_manager;
    cout<<"Contents of first is "<<int_memory_manager.get()<<endl;
    cout<<"Contents of second is "<<int_memory_manager2.get()<<endl;
    
    This sample program demonstrates that the overloaded copy operator for auto_ptr actually removes the pointer from the object being copied! It's set to NULL. This means that only one auto_ptr object can hold a pointer at any time. The act of assigning one auto_ptr to another changes the auto_ptr being assigned. Moreover, this situation holds true even when implicitly copying auto_ptr objects -- for instance, if you make a function call and pass an auto_ptr object, when the function returns, the contents of auto_ptr will be changed to NULL, as demonstrated by the following code:
    using namespace std;
    void aFunction(std::auto_ptr<int> x)
    {
    }
    
    int main()
    {
        std::auto_ptr<int> int_manager(new int);
        aFunction(int_manager);
        cout<<"Content of int_manager is "int_manager.get()<<endl;
        // Expected output: 0
    }
    
    In truth, this behavior is quite beneficial because it means that two auto_ptr objects will not both try to delete the same pointer. Deleting the same pointer twice is not a valid operation, and can lead to program crashes, whereas deleting NULL is a valid operation (though it doesn't change anything).

    A subtle consequence of this behavior is that auto_ptrs don't work well in all scenarios. For instance, using auto_ptr objects with the standard template library can lead to problems as some functions in the STL may make copies of the objects in containers such as the vector container class. One example is the sort function, which makes copies of some of the objects in the container being sorted. As a consequence, this copy can blithely delete the data in the container!

    If for some reason you did want to store an auto_ptr object in an STL container, you should probably either write your own memory manager container that counts the number of references to a pointer or handle freeing the memory somewhere else. If you wanted to take the second approach, you'll need to be able to tell an auto_ptr object that you're finished using it to manage your pointer. You can do this with the release function. For instance, the following code requests that an auto_ptr object allow us to handle the memory for the object again and resets the pointer stored by the auto_ptr object to NULL so that it doesn't get deleted twice.
    std::auto_ptr<int> int_memory_manager(new int);
    // Calling release sets the pointer managed by int_memory_manager to point 
    // to NULL
    int *need_to_delete_ptr = int_memory_manager.release();
    delete need_to_delete_ptr;
    
    Finally, if you happen to want to reuse an auto_ptr object, you can simply call the reset function to free the old memory and set the new memory:
    std::auto_ptr<int> int_memory_manager(new int);
    int_memory_manager.reset(new int);
    
    Using auto_ptr won't solve all of your problems. First, you could still write code that manually handles pointers that are also managed by auto_ptr objects. Doing this could result in double deletes. Whenever you request manual control of a pointer from an auto_ptr, you open yourself up to the requirement to call delete on that pointer -- consequently, the possibility of a memory leak exists.

    Summary

    The auto_ptr class is a templated class that takes a type and stores a pointer of that type, which can be set by the constructor or by using the reset function to pass in a new address to store. Pointers can be returned to manual control by the release function; otherwise, the pointer will be freed when the auto_ptr leaves scope.

    The Good
    • auto_ptr objects store pointers and handle deleting the pointer when the auto_ptr object goes out of scope
    • Using auto_ptr helps avoid memory leaks associated with exceptions and minimizes the amount of cleanup code required
    The Gotchas
    • Copying an auto_ptr changes the object being copied by setting the contests to NULL
    • auto_ptr objects are not guaranteed to work correctly with the standard template library containers

    posted on 2006-09-14 08:46 weidagang2046 閱讀(678) 評論(0)  編輯  收藏 所屬分類: C/C++

    主站蜘蛛池模板: 亚洲伦另类中文字幕| 久久久久亚洲AV无码去区首| 欧洲乱码伦视频免费| 国产亚洲精品美女| 亚洲精品无码永久中文字幕| 最近免费中文字幕大全高清大全1| 亚洲色大成网站WWW国产| 亚洲一本大道无码av天堂| 99re这里有免费视频精品| 久久久亚洲精华液精华液精华液 | 成年免费a级毛片| 亚洲AV成人无码久久精品老人| 夜夜嘿视频免费看| 免费人成在线观看视频高潮| 亚洲中文字幕一二三四区| 国产亚洲精品va在线| 日韩免费视频播播| 亚洲精品在线免费观看| 一个人看的免费观看日本视频www| 亚洲日本国产乱码va在线观看| 亚洲精品亚洲人成在线观看下载| 亚洲视频免费在线看| 精品一区二区三区免费观看 | 免费看成人AA片无码视频吃奶| 亚洲中文字幕乱码AV波多JI | 免费人妻精品一区二区三区| 亚洲卡一卡2卡三卡4麻豆| 中文字幕一精品亚洲无线一区| 在线观看免费毛片| 222www在线观看免费| 99re6在线视频精品免费| 日韩色日韩视频亚洲网站| 亚洲五月丁香综合视频| 久久精品亚洲综合| 亚洲色成人中文字幕网站| 亚洲精品国产电影| 成人免费无码精品国产电影| 91久久成人免费| 免费无码中文字幕A级毛片| 三级网站在线免费观看| 手机永久免费的AV在线电影网|