Размер класса шаблона - PullRequest
3 голосов
/ 13 мая 2011

Я написал шаблонный класс для циклического буфера:

template <class T> class CRingBuffer { /* ... */ };

Некоторые операции, выполняемые этим классом, основаны на точной оценке размера T.Кажется, это работает нормально, когда T равно BYTE (т.е. sizeof(T) == 1, проверьте).Однако, когда я пытаюсь использовать тот же класс, где T равен DWORD, по какой-то причине sizeof(T) оценивается как 16. В последний раз, когда я проверял, двойное слово составляет 4 байта, а не 16. Кто-нибудь знает почемуэто происходит?Спасибо.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Я не могу опубликовать все код из-за его проприетарной природы, но вот объявление класса иОпределение функции в вопросе:

template <class T> class CRingBuffer
{
#pragma pack( push , 1 )                // align on a 1-byte boundary

typedef struct BUFFER_FLAGS_tag
{
    T * pHead;                          // Points to next buffer location to write
    T * pTail;                          // Points to next buffer location to read
    BOOL blFull;                        // Indicates whether buffer is full.
    BOOL blEmpty;                       // Indicates whether buffer is empty.
    BOOL blOverrun;                     // Indicates buffer overrun.
    BOOL blUnderrun;                    // Indicates buffer underrun.
    DWORD dwItemCount;                  // Buffer item count.
} BUFFER_FLAGS, *LPBUFFER_FLAGS;

#pragma pack( pop )                     // end 1-byte boundary alignment

    // Private member variable declarations
private:
    T * m_pBuffer;                      // Buffer location in system memory
    T * m_pStart;                       // Buffer start location in system memory
    T * m_pEnd;                         // Buffer end location in system memory
    BUFFER_FLAGS m_tFlags;              // Buffer flags.
    DWORD m_dwCapacity;                 // The buffer capacity.

    // CRingBuffer
public:
    CRingBuffer( DWORD items = DEFAULT_BUF_SIZE );
    ~CRingBuffer();

    // Public member function declarations
public:
    DWORD Add( T * pItems, DWORD num = 1, LPDWORD pAdded = NULL );
    DWORD Peek( T * pBuf, DWORD num = -1, DWORD offset = 0, LPDWORD pWritten = NULL );
    DWORD Delete( DWORD num, LPDWORD pDeleted = NULL );
    DWORD Remove( T * pBuf, DWORD num = 1, LPDWORD pRemoved = NULL );
    void Flush( void );
    DWORD GetItemCount( void );
    BYTE GetErrorStatus( void );

    // Private member function declarations
private:
    void IncrementHead( LPBUFFER_FLAGS pFlags = NULL );
    void IncrementTail( LPBUFFER_FLAGS pFlags = NULL );
};

template <class T> void CRingBuffer<T>::IncrementHead( LPBUFFER_FLAGS pFlags )
{
    ASSERT(this->m_pBuffer != NULL);
    ASSERT(this->m_pStart != NULL);
    ASSERT(this->m_pEnd != NULL);
    ASSERT(this->m_tFlags.pHead != NULL);
    ASSERT(this->m_tFlags.pTail != NULL);

    pFlags = ( pFlags == NULL ) ? &(this->m_tFlags) : pFlags;

    // Verify overrun condition is not set.
    if ( pFlags->blOverrun == FALSE )
    {
        pFlags->pHead += sizeof(T); // increament buffer head pointer
        pFlags->blUnderrun = FALSE; // clear underrun condition

        // Correct for wrap condition.
        if ( pFlags->pHead == this->m_pEnd )
        {
            pFlags->pHead = this->m_pStart;
        }

        // Check for overrun.
        if ( pFlags->pHead == pFlags->pTail )
        {
            pFlags->blOverrun = TRUE;
        }
    }
}

Описанная выше проблема возникает при выполнении pFlags->pHead += sizeof(T); из IncrementHead.

1 Ответ

3 голосов
/ 13 мая 2011

О, это действительно очень просто:)

Не осознавая этого, в pFlags->pHead += sizeof(T); вы используете арифметику указателей.pHead - это указатель на T, и когда вы увеличиваете его на sizeof(T), это означает, что вы перемещаете его вперед на столько элементов типа T, а не на столько байтов, как вы думали.Таким образом, размер T становится в квадрате.Если ваша цель - переместить указатель на следующий элемент буфера, вы должны просто увеличить его на 1: pFlags->pHead += 1;

...