【问题标题】:Template Class Type Sizing模板类类型大小
【发布时间】:2011-05-12 21:40:08
【问题描述】:

我已经为循环缓冲区编写了一个模板类:

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

该类执行的某些操作依赖于对T 大小的准确评估。当TBYTE(即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-&gt;pHead += sizeof(T);时会出现上述问题。

【问题讨论】:

  • 在没有看到类模板的实现的情况下无法确定,但对齐/填充是一种猜测。
  • 你能提供一个小代码sn-p来演示这个问题吗,最好是没有任何其他依赖的可编译的?
  • 发布你正在使用的实际代码sizeof(T),以及你的类的完整定义。
  • 某些东西可能正在为您重新定义 DWORD,但由于我们掌握的信息极其有限,因此无法判断。
  • 我要出门了。当我明天早上第一件事时,我会为此发布一些代码。谢谢。

标签: c++ visual-studio-2008 templates sizeof circular-buffer


【解决方案1】:

哦,毕竟这真的很简单:)

不知不觉中,pFlags-&gt;pHead += sizeof(T); 使用了指针算法。 pHead 是一个指向T 的指针,当你将它增加sizeof(T) 时,这意味着你将它向前移动了那么多T 类型的元素,而不是你想象的那么多字节。所以T 的大小是平方的。如果您的目标是将指针移动到缓冲区的下一个元素,则只需将其增加 1:pFlags-&gt;pHead += 1;

【讨论】:

  • 你赢得了鹰眼奖!谢谢!
猜你喜欢
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
相关资源
最近更新 更多