C++通用数组实现

C++ generic array implementation

本文关键字:实现 数组 C++      更新时间:2023-10-16

我最近遇到了一个C++招聘测试。他们提出以下4个问题。

  1. 在以下Array类
  2. 为其中至少两个bug提供一个测试用例
  3. 为每个错误提出一个系数
  4. 假设我们有一个Array类的无错误实现,你认为它有什么设计问题吗
template <class T> class Array {
private:
    T *m_pData;
    unsigned int m_nSize;
public:
    Array(unsigned int nSize) : m_nSize( nSize)
    { 
        if ( m_nSize > 0)
            m_pData = new ( nothrow) T[ m_nSize];
    } 
    virtual ~Array() 
    { 
        if(m_pData != NULL)
            delete m_pData; 
    } 
    bool Set(unsigned int nPos, const T& Value) 
    {
        if(nPos < m_nSize) {
            m_pData[nPos] = Value;
            return true;
        }
        else 
            return false;
    }
    T Get(unsigned int nPos) {
        if(nPos < m_nSize) {
            return m_pData[nPos];
        }
        else 
            return T();
    }
};

问题是我看不到任何错误。是的,有一些奇怪的代码,比如:

  • 调用delete之前进行检查
  • 超出边界时在Get中返回默认值
  • 使用delete而不是delete[]

但这些对我来说不是bug。

以下是我一眼就能找到的五个错误:

  1. 使用nSize == 0创建实例不会初始化m_pData
  2. 如果分配失败,则m_nSize被设置为错误的值,随后的访问将失败
  3. 缺少复制构造函数
  4. 缺少赋值运算符
  5. delete应该是delete[](是的,NULL检查是多余的)

这些都是实际的错误,不可能有任何争论。其他弱点(我可以看到)"仅仅"是严重的设计缺陷。

四个错误:1.模板类Array{private:T*m_pData;unsigned int m_nSize;应该是

template <class T>
class Array 
{
    private: T *m_pData; unsigned int m_nSize;

2.在以下代码段

Array(unsigned int nSize) : m_nSize( nSize)
{ 
    if ( m_nSize > 0)
        m_pData = new ( nothrow) T[ m_nSize];
}

如果m_nSize小于0,则将m_pData指定为null;

3.在以下代码中:

virtual ~Array() 
{ 
    if(m_pData != NULL)
        delete m_pData; 
} 

使用delete[]m_pData代替delete,作为m_pData的数组。

  1. 在get和set函数中,在访问之前检查m_pData是否为NULL

概述:
1.最好在每个if-else上加大括号,即使是1行代码。-(有争议)
2.该if(m_pData != NULL)是冗余的。C++在delete和delete[]中检查空指针
3.你应该选择nullptr而不是NULL
4.Get本可以声明为const。本身不是bug
5.人们还使用匈牙利符号吗?

错误:
1.delete m_pData;应为delete[] m_pData;
根据该标准,删除而不是删除任何分配了new[]的内容都有未定义的行为
2.在构造函数中:new在内存不足的情况下不会抛出异常,但m_nSize无论如何都被设置为给定的大小。这可能会导致未来的错误——如果你试图分配10000个对象,但失败了,Get和Set仍然会超过*(m_pData + nPos),但这个内存地址无效。实际上应该是:if( m_pData ) {m_nSize = nSize ;}
3.Get and Set中的m_pData[nPos];:再次-构造函数没有抛出异常,m_pData可能为null。您需要检查m_pData是否为null。

扩展答案:
我确实意识到这是一个测试,用来检查人们对内存管理、面向obejct和一些模板使用的理解。然而,最好的答案是"没有必要重新发明轮子,std::vector比我们可能想到的任何天真的实现都更聪明。"把这句话作为对上面错误的补充,确实让你对专业C++开发人员会说的话有了答案。