2011-05-12 118 views
3

我写了一个模板类的循环缓冲区:模板类型定型

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

一些此类执行依靠T大小的准确评估的操作。当T是​​(即sizeof(T) == 1,检查)时,这似乎工作正常。但是,当我尝试使用TDWORD的同一班级时,出于某种原因,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; 
     } 
    } 
} 

问题当执行IncrementHeadpFlags->pHead += sizeof(T);时发生上述情况。

+1

不可能明确地说没有看到类模板的实现,但对齐/填充是一个猜测。 – ildjarn 2011-05-12 21:44:30

+2

你能否提供一个小的代码片段来演示这个问题,最好是一个没有任何其他依赖的可编译的代码片段? – 2011-05-12 21:44:57

+3

发布你正在做'sizeof(T)'的实际代码,以及你的类的完整定义。 – 2011-05-12 21:47:58

回答

3

哦,这是没有意识到这一切:)

后很简单,在pFlags->pHead += sizeof(T);你使用指针运算。 pHead是指向T的指针,当您将其增加sizeof(T)时,这意味着您将它移动到许多类型为T的元素,而不是像您想象的那么多字节。所以T的大小被平方。如果你的目标是将指针移动到缓冲区的下一个元素,你应该增加1:pFlags->pHead += 1;

+0

Ahahaha,很好找! :D – Xeo 2011-05-13 14:56:29

+0

您赢得了鹰眼奖!谢谢! – 2011-05-13 15:31:18