<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人片在线观看| 日韩高清免费观看| 好男人www免费高清视频在线| 免费观看的毛片大全| 野花高清在线观看免费完整版中文| A级毛片内射免费视频| 亚洲Av综合色区无码专区桃色| 亚洲成AV人片一区二区密柚| 久久久久久久亚洲Av无码| 亚洲天堂中文资源| 亚洲va久久久久| 亚洲国产欧美一区二区三区| 免费国产a理论片| 在线观看免费成人| 亚洲人成网站18禁止一区| 精品久久香蕉国产线看观看亚洲| 亚洲日本中文字幕区| 日韩a级无码免费视频| 色影音免费色资源| 亚洲AV成人潮喷综合网| 久久精品视频亚洲| 三级网站在线免费观看| 国产四虎免费精品视频| 亚洲国产综合专区电影在线| 久久er国产精品免费观看2| 最新中文字幕电影免费观看| 91麻豆国产自产在线观看亚洲 | 中国xxxxx高清免费看视频| 亚色九九九全国免费视频| 亚洲国产高清视频| 99热这里只有精品免费播放| 亚洲国产精品久久久久| 三年片在线观看免费大全电影 | 男女做羞羞的事视频免费观看无遮挡| 久久久久久亚洲精品成人| 免费福利视频导航| 狠狠综合久久综合88亚洲| 国产V片在线播放免费无码| 青青在线久青草免费观看|