青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

DXUT源碼分析 ---- 類CGrowableArray

CGrowableArray是DXUT實現的一個可自動增長的模板類數組,類似于STL里的vector,該類的實現在DXUTmisc.h里。


首先來看看它的定義部分:

//--------------------------------------------------------------------------------------
// A growable array
//--------------------------------------------------------------------------------------
template< typename TYPE >
class CGrowableArray
{
public:
    CGrowableArray()  
    { 
        m_pData        
= NULL; 
        m_nSize        
= 0
        m_nMaxSize    
= 0
    }

    CGrowableArray( 
const CGrowableArray<TYPE>& a ) 
    { 
        
forint i=0; i < a.m_nSize; i++ ) 
            Add( a.m_pData[i] ); 
    }

    
~CGrowableArray() 
    { 
        RemoveAll(); 
    }

    
const TYPE& operator[]( int nIndex ) const  { return GetAt( nIndex ); }
    TYPE
& operator[]( int nIndex )                { return GetAt( nIndex ); }
   
    CGrowableArray
& operator=const CGrowableArray<TYPE>& a ) 
    { 
        
ifthis == &a ) 
            
return *this
        
        RemoveAll(); 
        
        
forint i=0; i < a.m_nSize; i++ ) 
            Add( a.m_pData[i] ); 
        
        
return *this
    }

    HRESULT SetSize( 
int nNewMaxSize );
    HRESULT Add( 
const TYPE& value );
    HRESULT Insert( 
int nIndex, const TYPE& value );
    HRESULT SetAt( 
int nIndex, const TYPE& value );

    TYPE
&   GetAt( int nIndex ) 
    { 
        assert( nIndex 
>= 0 && nIndex < m_nSize ); 
        
return m_pData[nIndex]; 
    }

    
int     GetSize() const                    { return m_nSize; }
    TYPE
*   GetData()                        { return m_pData; }
    
bool    Contains( const TYPE& value )    { return ( -1 != IndexOf( value ) ); }

    
int IndexOf( const TYPE& value ) 
    { 
        
return ( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1
    }

    
int IndexOf( const TYPE& value, int iStart ) 
    { 
        
return IndexOf( value, iStart, m_nSize - iStart ); 
    }

    
int IndexOf( const TYPE& value, int nIndex, int nNumElements );

    
int LastIndexOf( const TYPE& value ) 
    { 
        
return ( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize ) : -1
    }

    
int LastIndexOf( const TYPE& value, int nIndex ) 
    { 
        
return LastIndexOf( value, nIndex, nIndex+1 ); 
    }

    
int LastIndexOf( const TYPE& value, int nIndex, int nNumElements );

    HRESULT Remove( 
int nIndex );
    
void    RemoveAll() { SetSize(0); }

protected:
    TYPE
* m_pData;      // the actual array of data
    int m_nSize;        // # of elements (upperBound - 1)
    int m_nMaxSize;     // max allocated

    HRESULT SetSizeInternal( 
int nNewMaxSize );  // This version doesn't call constructor or destructor.
};

 

 

SetSizeInternal() 分析

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::SetSizeInternal( int nNewMaxSize )
{
    
if( nNewMaxSize < 0 )
    {
        assert( 
false );
        
return E_INVALIDARG;
    }

    
if( nNewMaxSize == 0 )
    {
        
// Shrink to 0 size & cleanup
        if( m_pData )
        {
            free( m_pData );
            m_pData 
= NULL;
        }

        m_nMaxSize 
= 0;
        m_nSize       
= 0;
    }
    
else if( m_pData == NULL || nNewMaxSize > m_nMaxSize )
    {
        
// Grow array
        int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize;
        nNewMaxSize 
= __max( nNewMaxSize, m_nMaxSize + nGrowBy );

        TYPE
* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) );
        
if( pDataNew == NULL )
            
return E_OUTOFMEMORY;

        m_pData       
= pDataNew;
        m_nMaxSize 
= nNewMaxSize;
    }

    
return S_OK;
}

SetSizeInternal()是protected類型的方法,主要供其他方法內部調用,函數首先檢查nNewMaxSize是否合法,如果nNewMaxSize為0則釋放分配的內存,如果m_pData為NULL或者指定的nNewMaxSize大于原先分配的內存大小m_nMaxSize,則重新分配內存。

// Grow array
int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize;  

如果m_nMaxSize為0,意味著沒有為m_nMaxSize指定大小,則將nGrowBy賦值為16,即增加的內存大小為16 * sizeof(TYPE);若指定了m_nMaxSize,則增加的大小為m_nMaxSize * sizeof(TYPE),即將分配內存調整為原來的兩倍。

nNewMaxSize = __max( nNewMaxSize, m_nMaxSize + nGrowBy );

#define __max(a,b) (((a) > (b)) ? (a) : (b))

nNewMaxSize在新指定分配內存大小與自動增長的內存m_nMaxSize + nGrowBy 中取一個較大的值。

TYPE* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) );
if( pDataNew == NULL )
        return E_OUTOFMEMORY;

m_pData       = pDataNew;
m_nMaxSize = nNewMaxSize;

pDataNew為指向重新分配內存的指針,m_pData = pDataNew將m_pData指向新分配的內存,m_nMaxSize = nNewMaxSize更新分配后內存的最大尺寸。

函數realloc()的聲明如下:

Reallocate memory blocks.

 
void *realloc(
void *memblock,
size_t size
);

Parameters

memblock
Pointer to previously allocated memory block.
size
New size in bytes.

Return Value

realloc returns a void pointer to the reallocated (and possibly moved) memory block.

If there is not enough available memory to expand the block to the given size, the original block is left unchanged, and NULL is returned.

If size is zero, then the block pointed to by memblock is freed; the return value is NULL, and memblock is left pointing at a freed block.

The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.

Remarks

The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to calloc, malloc, or realloc.

The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument.

In Visual C++ 2005, realloc sets errno to ENOMEM if the memory allocation fails or if the amount of memory requested exceeds _HEAP_MAXREQ. For information on this and other error codes, see errno, _doserrno, _sys_errlist, and _sys_nerr.

realloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode. The new handler mode indicates whether, on failure, malloc is to call the new handler routine as set by _set_new_handler. By default, malloc does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when realloc fails to allocate memory, malloc calls the new handler routine in the same way that the new operator does when it fails for the same reason. To override the default, call

_set_new_mode(1)

early in ones program, or link with NEWMODE.OBJ (see Link Options).

When the application is linked with a debug version of the C run-time libraries, realloc resolves to _realloc_dbg. For more information about how the heap is managed during the debugging process, see The CRT Debug Heap.

realloc is marked __declspec(noalias) and __declspec(restrict), meaning that the function is guaranteed not to modify global variables, and that the pointer returned is not aliased. For more information, see noalias and restrict.

Requirements

Routine Required header Compatibility
realloc <stdlib.h> and <malloc.h> ANSI, Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003

For additional compatibility information, see Compatibility in the Introduction.

Example

// crt_realloc.c
// This program allocates a block of memory for buffer and then uses _msize to display the size of that
// block. Next, it uses realloc to expand the amount of memory used by buffer and then calls _msize again to
// display the new amount of memory allocated to buffer.

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

int main( void )
{
long *buffer, *oldbuffer;
size_t size;

if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )
exit( 1 );

size = _msize( buffer );
printf( "Size of block after malloc of 1000 longs: %u\n", size );

// Reallocate and show new size:
oldbuffer = buffer; // save pointer in case realloc fails
if( (buffer = realloc( buffer, size + (1000 * sizeof( long )) ))
== NULL )
{
free( oldbuffer ); // free original block
exit( 1 );
}
size = _msize( buffer );
printf( "Size of block after realloc of 1000 more longs: %u\n",
size );

free( buffer );
exit( 0 );
}

Output

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

 

SetSize()分析

原代碼:

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::SetSize( int nNewMaxSize )
{
    
int nOldSize = m_nSize;

    
if( nOldSize > nNewMaxSize )
    {
        
// Removing elements. Call destructor.
        forint i = nNewMaxSize; i < nOldSize; ++i )
            m_pData[i].
~TYPE();
    }

    
// Adjust buffer.  Note that there's no need to check for error
    
// since if it happens, nOldSize == nNewMaxSize will be true.
    HRESULT hr = SetSizeInternal( nNewMaxSize );

    
if( nOldSize < nNewMaxSize )
    {
        
// Adding elements. Call constructor.
        forint i = nOldSize; i < nNewMaxSize; ++i )
            ::
new (&m_pData[i]) TYPE;
    }

    
return hr;
}

個人覺得這代碼寫的有些問題,作者說如果調用SetSizeInternal()失敗,則nOldSize == nNewMaxSize必成立,但實際上我們查看SetSizeInternal()的代碼發現:

TYPE* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) );
 if( pDataNew == NULL )
       return E_OUTOFMEMORY;

也就是說當realloc()失敗的時候SetSizeInternal()調用會失敗,這時nOldSize為m_nSize,它不會恒等于nNewMaxSize,于是我將上面的代碼修改為:

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::SetSize( int nNewMaxSize )
{
    
int nOldSize = m_nSize;

    
if( nOldSize > nNewMaxSize )
    {
        
// Removing elements. Call destructor.
        forint i = nNewMaxSize; i < nOldSize; ++i )
            m_pData[i].
~TYPE();
    }

    
// Adjust buffer.  
    HRESULT hr = SetSizeInternal( nNewMaxSize );

    
if(FAILED(hr))
        
return hr;

    
if( nOldSize < nNewMaxSize )
    {
        
// Adding elements. Call constructor.
        forint i = nOldSize; i < nNewMaxSize; ++i )
            ::
new (&m_pData[i]) TYPE;
    }

    
return S_OK;
}

函數首先將原先內存中的已賦值的元素個數保存為nOldSize,接下來的代碼:

    if( nOldSize > nNewMaxSize )
    {
        // Removing elements. Call destructor.
        for( int i = nNewMaxSize; i < nOldSize; ++i )
            m_pData[i].~TYPE();
    }

檢查新指定的內存大小是否小于已分配內存中已賦值元素的個數,如果是則顯式調用各元素的析構函數釋放資源,如下圖所示:


接著調用SetSizeInternal()重新分配大小,失敗則返回:

    // Adjust buffer.  
    HRESULT hr = SetSizeInternal( nNewMaxSize );

    if(FAILED(hr))
        return hr;

如果nNewMaxSize大于nOldSize,則調用構造函數初始化元素的數據,如下圖所示:


    if( nOldSize < nNewMaxSize )
    {
        // Adding elements. Call constructor.
        for( int i = nOldSize; i < nNewMaxSize; ++i )
            ::new (&m_pData[i]) TYPE;
    }

這里對顯式調用構造函數和析構函數做一些說明,之所以顯式調用,是因為new沒有renew,而malloc和calloc有realloc,調用realloc可以避免頻繁調用malloc()和free()【或者new和delete】造成的性能損失,而realloc()不會自動調用構造和析構函數,所以需要顯式調用。


Add()分析:

源碼:

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::Add( const TYPE& value )
{
    HRESULT hr;

    
if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
        
return hr;

    
// Construct the new element
    ::new (&m_pData[m_nSize]) TYPE;
    
    m_pData[m_nSize] 
= value;
    
++m_nSize;

    
return S_OK;
}

代碼相當明了,首先調用SetSizeInternal()分配大小,然后調用構造函數,給m_pData對應位置的元素賦值,接著增加m_nSize的大小。
需要說明的是SetSizeInternal()并不會每調用一次Add()就重新分配內存,只有當指定的元素個數超過了m_nMaxSize的時候才會重新分配內存。

 

Insert()分析:

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::Insert( int nIndex, const TYPE& value )
{
    HRESULT hr;

    
// Validate index
    if( nIndex < 0 || nIndex > m_nSize )
    {
        assert( 
false );
        
return E_INVALIDARG;
    }

    
// Prepare the buffer
    if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
        
return hr;

    
// Shift the array
    MoveMemory( &m_pData[nIndex+1], &m_pData[nIndex], sizeof(TYPE) * (m_nSize - nIndex) );

    
// Construct the new element
    ::new (&m_pData[nIndex]) TYPE;

    
// Set the value and increase the size
    m_pData[nIndex] = value;
    
++m_nSize;

    
return S_OK;
}

Insert()在指定位置nIndex插入一個元素,函數通過MoveMemory()來移動內存,它的定義如下:

#define MoveMemory RtlMoveMemory

#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))

接著調用構造函數,賦值,增加m_nSize的大小。

 

SetAt():

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::SetAt( int nIndex, const TYPE& value )
{
    
// Validate arguments
    if( nIndex < 0 || nIndex >= m_nSize )
    {
        assert( 
false );
        
return E_INVALIDARG;
    }

    m_pData[nIndex] 
= value;
    
return S_OK;
}


IndexOf():
 
//--------------------------------------------------------------------------------------
// Searches for the specified value and returns the index of the first occurrence
// within the section of the data array that extends from iStart and contains the 
// specified number of elements. Returns -1 if value is not found within the given 
// section.
//--------------------------------------------------------------------------------------
template< typename TYPE >
int CGrowableArray<TYPE>::IndexOf( const TYPE& value, int iStart, int nNumElements )
{
    
// Validate arguments
    if( iStart < 0 || iStart >= m_nSize || nNumElements < 0 || iStart + nNumElements > m_nSize )
    {
        assert( 
false );
        
return -1;
    }

    
// Search
    forint i = iStart; i < (iStart + nNumElements); i++ )
    {
        
if( value == m_pData[i] )
            
return i;
    }

    
// Not found
    return -1;
}

 

LastIndexOf():

//--------------------------------------------------------------------------------------
// Searches for the specified value and returns the index of the last occurrence
// within the section of the data array that contains the specified number of elements
// and ends at iEnd. Returns -1 if value is not found within the given section.
//--------------------------------------------------------------------------------------
template< typename TYPE >
int CGrowableArray<TYPE>::LastIndexOf( const TYPE& value, int iEnd, int nNumElements )
{
    
// Validate arguments
    if( iEnd < 0 || iEnd >= m_nSize || nNumElements < 0 || iEnd - nNumElements < 0 )
    {
        assert( 
false );
        
return -1;
    }

    
// Search
    forint i = iEnd; i > (iEnd - nNumElements); i-- )
    {
        
if( value == m_pData[i] )
            
return i;
    }

    
// Not found
    return -1;
}

 

Remove():

template< typename TYPE >
HRESULT CGrowableArray
<TYPE>::Remove( int nIndex )
{
    
if( nIndex < 0 || nIndex >= m_nSize )
    {
        assert( 
false );
        
return E_INVALIDARG;
    }

    
// Destruct the element to be removed
    m_pData[nIndex].~TYPE();

    
// Compact the array and decrease the size
    MoveMemory( &m_pData[nIndex], &m_pData[nIndex+1], sizeof(TYPE) * (m_nSize - (nIndex+1)) );
    
--m_nSize;

    
return S_OK;
}

 

posted on 2008-05-18 14:05 lovedday 閱讀(2496) 評論(0)  編輯 收藏 引用 所屬分類: ■ DXUT Research

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美日韩国产一级| 亚洲日本无吗高清不卡| 在线欧美一区| 国产婷婷色一区二区三区| 国产日韩久久| 国内精品久久国产| 在线日韩成人| 一区二区三区免费看| 亚洲欧美日韩一区在线观看| 欧美一区二视频在线免费观看| 久久精品视频在线免费观看| 免费不卡中文字幕视频| 欧美成人在线影院| 宅男精品导航| 男人的天堂亚洲| 国产精品影片在线观看| 亚洲国产精品电影| 一级日韩一区在线观看| 久久福利一区| 欧美大片在线观看一区| 亚洲天堂网站在线观看视频| 久久av一区二区三区| 欧美人与禽猛交乱配视频| 国产欧美精品xxxx另类| 亚洲激情视频在线| 性欧美精品高清| 亚洲电影免费在线| 性色一区二区| 欧美色偷偷大香| 伊人婷婷欧美激情| 亚洲免费人成在线视频观看| 欧美激情一区二区三区四区| 亚洲欧美日韩视频一区| 欧美电影在线| 黄色成人在线网址| 午夜精品久久久| 亚洲伦理一区| 欧美极品aⅴ影院| 激情成人中文字幕| 欧美一区在线看| 日韩亚洲欧美高清| 免费中文日韩| 在线观看成人av| 久久狠狠婷婷| 亚洲欧美日韩系列| 国产精品影音先锋| 亚洲视频在线观看视频| 亚洲国产日韩欧美在线99| 欧美在线视频一区二区三区| 欧美亚州一区二区三区 | 国产欧美日韩综合一区在线观看 | 亚洲视频在线观看| 久久五月婷婷丁香社区| 国产日韩欧美精品| 性高湖久久久久久久久| 99riav久久精品riav| 欧美电影美腿模特1979在线看 | 亚洲男人的天堂在线| 亚洲精选在线| 欧美三级日本三级少妇99| 999在线观看精品免费不卡网站| 欧美高清视频一区| 欧美国产在线视频| 日韩一级片网址| 亚洲欧洲三级| 欧美日韩精品高清| 亚洲视频免费| 亚洲在线中文字幕| 国产综合亚洲精品一区二| 久久人人爽人人爽爽久久| 久久久久久国产精品一区| 在线看片欧美| 亚洲国产成人久久综合一区| 欧美成人一区二免费视频软件| 亚洲美女毛片| 在线亚洲一区二区| 国产欧美日韩精品在线| 老司机aⅴ在线精品导航| 老色鬼精品视频在线观看播放| 亚洲激情小视频| 99视频精品| 国产日韩欧美精品综合| 欧美国产日本| 欧美系列电影免费观看| 久久精品人人做人人爽| 久久在线免费观看| 一区二区三区精品久久久| 中文在线一区| 永久域名在线精品| 亚洲精品黄网在线观看| 国产精品人成在线观看免费 | 欧美激情综合网| 亚洲欧美精品suv| 欧美一级网站| 亚洲人线精品午夜| 亚洲综合视频1区| 亚洲国产精品一区二区www| 亚洲欧洲日产国产综合网| 国产精品视频免费| 亚洲电影免费观看高清完整版在线| 欧美色123| 欧美国产免费| 国产精品视频| 亚洲人午夜精品免费| 国产一区二区你懂的| 狂野欧美一区| 亚洲美女av网站| 一本色道久久88综合亚洲精品ⅰ| 国产日韩欧美一区| 亚洲精品女人| 国产精品一区二区在线| 欧美国产一区在线| 国产日韩欧美另类| 99re66热这里只有精品4| 亚洲二区视频| 久久久91精品| 欧美一区二区三区在| 欧美了一区在线观看| 欧美成年人网| 狠狠色狠狠色综合人人| 亚洲无限av看| 一区二区精品国产| 欧美岛国在线观看| 欧美成人福利视频| 在线免费观看一区二区三区| 欧美一区二区三区四区高清| 欧美一二三区在线观看| 国产精品久久久久久久久久久久久| 亚洲国产精品一区二区久 | 亚洲性图久久| 欧美日韩成人| 亚洲精选一区二区| 亚洲深夜福利| 欧美日韩亚洲激情| 亚洲精品视频免费| 一区二区日韩| 国产精品jvid在线观看蜜臀| 亚洲美女电影在线| 亚洲午夜一区二区| 国产精品久久久久久久第一福利| 亚洲免费观看| 亚洲伊人一本大道中文字幕| 国产精品成人一区二区三区夜夜夜 | 欧美激情四色| 亚洲精品美女在线| 宅男精品视频| 欧美日韩日本视频| 亚洲一区在线播放| 久久爱www久久做| 国产亚洲欧美另类中文| 久久国产精品黑丝| 麻豆精品一区二区综合av| 亚洲第一综合天堂另类专| 欧美成年视频| 99国产一区| 欧美影院一区| 在线成人中文字幕| 欧美伦理影院| 亚洲影院免费观看| 久久久久网站| 日韩午夜精品视频| 国产欧美日韩在线视频| 久久综合网色—综合色88| 亚洲三级影院| 欧美在线观看一区| 亚洲第一免费播放区| 国产精品日韩欧美一区| 欧美午夜精品久久久久久人妖| 裸体丰满少妇做受久久99精品 | 亚洲女与黑人做爰| 欧美日韩日本网| 亚洲一区二区三区精品视频| 久久不射中文字幕| 最新国产の精品合集bt伙计| 欧美日韩午夜激情| 亚洲欧美韩国| 亚洲国产日韩在线| 欧美专区日韩视频| 在线播放亚洲| 国产精品大片| 久久久噜噜噜久久中文字幕色伊伊 | 午夜伦理片一区| 欧美激情精品久久久久久免费印度 | 久久亚洲捆绑美女| 中文精品一区二区三区| 精品999在线观看| 国产精品久久久久毛片软件 | 亚洲一区bb| 亚洲福利视频一区| 久久久久国产精品午夜一区| 亚洲视频在线免费观看| 亚洲国产精品毛片| 黄色日韩精品| 国产精品综合色区在线观看| 欧美激情一区二区三区在线视频| 久久成人18免费观看| 亚洲天堂久久| 在线视频亚洲欧美| 日韩网站在线| 亚洲精品乱码久久久久久黑人 |