2011-05-12 117 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