• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            鍵盤上的舞者

            My Email: marckywu@gmail.com
            隨筆 - 19, 文章 - 0, 評論 - 3, 引用 - 0
            數據加載中……

            Allocating Arrays Using Placement new (zz)

                   An additional version of operator new enables you to construct an object or an array of objects at a predetermined memory position. This version is called placement new and has many useful applications, including building a custom-made memory pool or a garbage collector. Additionally, it can be used in mission-critical applications because there's no danger of allocation failure; the memory that's used by placement new has already been allocated. Placement new is also faster because the construction of an object on a preallocated buffer takes less time.

            You already know how to use placement new to allocate a single object on a predetermined memory address. However, some programming tasks require the allocation of arrays on a predetermined memory address. Here's how you do it.

            Placement new Overview

            Mobile devices, embedded systems and custom garbage collectors are only a few instances of programming environments that may require placement new allocation of arrays. Before I discuss the details of such array allocations, let's remind ourselves briefly how scalar (i.e. non-array) placement new works.

            The scalar version of placement new takes a user-supplied address on which it constructs a single object. Unlike the ordinary version of the new operator, placement new doesn't allocate storage for the object; it merely constructs the object on the memory address you provide:

            #include <new> //required for using placement new
            class Widget {
            public:
                Widget();
                
            virtual ~Widget
                
            virtual void Draw();
            };
            char* buf=new char [sizeof (Widget)];//preallocate
            Widget* widget= new(buf) Widget; //construct Widget on buf
            widget->Draw(); //use Widget

            To destroy widget you first have to invoke its destructor explicitly:

            widget->~Widget(); //explicit destructor invocation

            Next, reclaim the raw memory like this:

            delete[] buf;

            Array Allocation

            Allocating arrays with placement new follows the same steps more or less, but you have to pay attention to additional nuances. Here is a step-by-step guide:

            First, allocate a buffer large enough to hold an array of the desired type:

            const int ARRSIZE = 15;
            char * buf= new [sizeof(Widget)*ARRSIZE];

            Don't be tempted to calculate the size manually; always use sizeof to ensure that the buffer is properly aligned and has the right size.

            Next, construct an array of ARRSIZE objects on the buffer using placement new[] :

            Widget* widgets=new(buf) Widget[ARRSIZE];//construct an array

            You can now use the allocated array as usual:

            for (int i=0; i<ARRSIZE; i++)
            {
             widgets[i].Draw();
            }
            Make sure that your target class -- Widget in this example -- has a public default constructor. Otherwise, it would be impossible to create arrays thereof.

            Destroying the Array

            To destroy such an array allocated by placement new you have to call the destructor for each element explicitly:

            int i=ARRSIZE;
            while (i)
                widgets[
            --i].~Widget();

            The while -loop uses a descending order to preserve the canonical destruction order of C++ -- the object that was constructed last must be destroyed first. To comply with this requirement, the element with the highest index is destroyed first.

            Finally, you release the raw memory on which the array resided by calling delete[] :

            delete[] buf;

            Performance Tuning

            The array placement new has a potential performance problem: it initializes every element in the array unconditionally. If your app deals with large arrays, this isn't the most efficient way. In some apps only a portion of the array is actually used, and in other apps the elements are assigned a different value immediately after their construction. In these cases, you want to postpone, or even completely avoid, the automatic initialization of array elements. To avoid the initialization of placement new arrays, follow the following steps:

            As before, begin with an allocation of a raw buffer with the appropriate size. This time however, use the global operator new instead of the new operator:

            Widget * warr=
            static_cast
            <Widget*> (::operator new ( sizeof(Widget)* ARRSIZE));

            The global operator new , very much like C's malloc() , merely allocates raw bytes of memory from the free-store, without initializing them. It returns void * rather than Widget* which is why you need to cast the result explicitly.

            At this stage, warr is a pointer to raw memory. You can't access its elements because they haven't been initialized yet. To initialize individual elements, call placement new once more, for each element you want initialized:

            void assign(Widget arr[], size_t & sz,  const Widget& init)
            {
                
            new (&arr[sz++]) Widget (init); //invoke copy ctor
            }

            assign() passes the address of an individual element to placement new which in turn invokes Widget 's copy constructor. The copy-constructor initializes that element with init . Using this technique, you can initialize elements selectively, leaving the rest of the array uninitialized.

            To destroy such an array, invoke the destructor of every initialized object. Then call the global operator delete to reclaim the raw storage:

            void destroy(Widget arr[], size_t & sz)
            {
                
            while (sz)
                {
                    arr[
            --sz].~Widget();//destroy all initialized elements
                }
                 ::
            operator delete (arr); //reclaim raw storage
            }

            Summary

            The techniques I've presented here are bug prone. Therefore, they should be encapsulated in higher-level classes that hide the implementation details from users. These techniques aren't rarely-used as they might seem. STL allocators use them under the hood to avoid object initialization and minimize reallocations.



            posted on 2009-08-13 00:48 Marcky 閱讀(367) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

            久久国产香蕉视频| 精品久久久无码中文字幕天天| 日韩中文久久| 99久久99久久精品国产片果冻| 人妻无码αv中文字幕久久| 人妻精品久久无码专区精东影业 | 久久丝袜精品中文字幕| 91秦先生久久久久久久| 国产L精品国产亚洲区久久| 蜜臀久久99精品久久久久久| 漂亮人妻被中出中文字幕久久| 国内精品久久久久久99蜜桃| 久久久久久A亚洲欧洲AV冫| 一本一本久久a久久综合精品蜜桃| 国产V亚洲V天堂无码久久久| 亚洲国产天堂久久久久久 | 狠狠色丁香婷婷综合久久来| 久久精品国产亚洲Aⅴ香蕉| 国产精品美女久久久久| 国产A三级久久精品| 久久青青草原精品国产软件| 99久久精品国产高清一区二区| 久久精品国产99国产精品亚洲| 成人国内精品久久久久影院VR| 亚洲精品乱码久久久久久久久久久久 | 一本一道久久精品综合| 久久久久亚洲精品无码蜜桃| 久久香蕉国产线看观看猫咪?v| 99精品久久精品| 国产成人精品白浆久久69| 久久人人爽人人爽人人AV东京热 | 中文精品久久久久国产网址| 久久精品人人做人人爽电影蜜月| 久久亚洲日韩看片无码| 久久精品国产99国产精品导航| 亚洲七七久久精品中文国产| 午夜精品久久久久9999高清| 久久夜色精品国产亚洲av| 久久国产综合精品五月天| 国产精品99久久久久久董美香| 久久国产精品国语对白|