【问题标题】:C++ generic array implementationC++ 泛型数组实现
【发布时间】:2015-06-29 09:12:47
【问题描述】:

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

  1. 在实现中至少有 4 个不同的错误 下面的数组类。
  2. 为每个错误至少为其中 2 人提供一个测试用例。
  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();
    }
};

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

  • 调用删除前检查
  • 越界时在 Get 中返回默认值
  • 使用删除而不是删除 []

但这些对我来说不是错误。

【问题讨论】:

  • (1) delete m_pData; 应该是 delete [] m_pData;
  • 看看你的构造函数。如果m_nSize == 0 会发生什么? m_pData 指针将设置为什么?此外,在发出delete 时无需测试 NULL。代码存在错误样式问题。
  • 没有复制构造函数或赋值运算符。
  • 如果new (nothrow) 返回 nullptr 会怎样?
  • 默认构造一个T 来返回一个越界的Get 似乎很荒谬。

标签: c++ arrays generics


【解决方案1】:

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

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

这些都是实际的错误,无法争论。其他弱点(我可以看到)“仅仅是”严重的设计缺陷。

【讨论】:

    【解决方案2】:

    四个错误: 1. 模板类 Array { private: T *m_pData;无符号整数 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.在cpode下面:

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

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

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

    【讨论】:

    • (1) 只是问题中的格式错误,而不是代码中的实际错误。
    • @KonradRudolph 好的
    • m_nSize 不能小于 0,因为它是无符号的。
    【解决方案3】:

    一般:
    1. 最好在每个 if-else 上加上花括号,即使是 1 行代码也是如此。 - (有争议)
    2. 这个if(m_pData != NULL) 是多余的。 C++ 在 delete 和 delete[] 中检查空指针
    3. 你应该选择nullptr 而不是NULL
    4.Get 可以被声明为 const。本身不是错误
    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. m_pData[nPos]; in Get and Set: 再次 - 构造函数不会抛出异常,m_pData 可能为空。您需要检查m_pData 是否不为空。

    扩展答案:
    我确实意识到这是一个测试,以检查人们在内存管理、面向对象和一些模板使用方面的理解。然而,最好的答案将是“没有必要重新发明轮子,std::vector 比我们可能想到的任何幼稚实现都更聪明。” 说这是对上述错误的补充,确实提高了您对专业 C++ 开发人员会说的话的回答。

    【讨论】:

    • (强烈)不同意 1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多