使用数组外部地址的数组运算符

时间:2014-01-03 14:53:31

标签: c++ arrays

我最近遇到了一个C ++类,它实现了一个非零索引的数组。即可以将此类初始化为具有15..19的有效索引范围。此类计算索引为0的元素的地址,即使这可能超出分配的地址空间并存储该地址。然后使用此元素0地址通过operator []处理元素访问。一些示例代码(简化):

template <typename T>
class NonZeroArray
{ 

public: 

NonZeroArray(int min_index, int size, T default_element) : 
    m_min_index(min_index), 
    m_size(size),
    m_default_element(default_element)
{
    m_base_address = (T*) malloc(size*sizeof(T));
    m_zero_index_adress = m_base_address - min_index;
}

~NonZeroArray()
{
    free(m_base_address);
}

T& element(int index) 
{
    if ( index < m_min_index || index >= m_min_index + m_size) 
        return m_default_element;
    else
        return m_zero_index_adress[index];
} 

private:
    int m_min_index;
    int m_size;
    T* m_base_address;
    T* m_zero_index_adress;
    T m_default_element;
};

这对我来说似乎不太复杂。我真的不明白为什么开发人员没有选择通过m_base_address [index + m_min_index]实现元素访问。但更糟糕的是,我担心目前的实施可能会很危险。代码似乎可靠地工作但我想知道如果在m_zero_index_address的计算中存在算术溢出会发生什么,即如果最小索引偏移量大于allocatead地址。是否有可能出现严重错误或者此代码是否安全?

1 个答案:

答案 0 :(得分:7)

你的直觉是正确的。

将指针形成为远离数组范围的未定义,溢出是一个非常现实的问题,作者应该完全按照你的建议完成。

  

[C++11: 5.7/5]:当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。 [..] 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义