c++ - 模板化类中的析构函数实现

标签 c++ class templates destructor delete-operator

如果我有这样的类(class):

template <class T>                            
class Array {                                              
 private:                                        
  T *m_pData;                                   
  unsigned int m_nSize;                         
 public:                                         
 Array(unsigned int nSize) : m_nSize(nSize),m_pData(nullptr) {                                           
 if(m_nSize > 0)
  m_pData = new T[m_nSize];                
 }                                           

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

如果现在我像这样创建我的类的对象:

Array<int> miArray(5);

析构函数的实现应该没问题,但是如果我创建一个这样的对象:

Array<int*> miArray(5);

在析构函数中,我应该删除存储在数组中的每个对象以避免内存泄漏。

我怎样才能做到这一点?

谢谢

最佳答案

你可以使用 a specialization of your destructor ,或将标记分派(dispatch)到删除函数(这会更灵活)。然而,这会导致一个非常笨拙和脆弱的设计。假设您已经实现了相当于 push_back 的功能,考虑这些用户代码片段:

{
    Array<int*> arr;
    arr.push_back(new int(42)); // new is on the side of the user
} // ... but delete is not. Weird.

这也会导致一整类错误:你应该只给出 new编辑T s 到 Array<T*> ,但是没有任何安全措施可以防止传入其他内容:

{
    Array<int*> arr;
    int i = 42;
    arr.push_back(&i); // No diagnostic
    arr.push_back(new int[17]); // No diagnostic either
} // Undefined behaviour from calling `delete` on stuff that hasn't been `new`ed

所有这些都是没有原始拥有指针规则存在的原因:原始指针根本不应该管理资源生命周期。如果我使用 Array<int*> ,它应该存储我的指针并让我使用它们,但绝不永远 delete他们,因为那是试图管理生命周期。

相反,如果我想要一个 Array管理生命周期的,我将使用相应的智能指针,使用 Array<std::unique_ptr<int>> .这与 Array 很好地联系在一起,要求它只调用所包含对象的析构函数(它已经这样做了)。这些析构函数(即 ~unique_ptr)将按照它们的工作传递地释放资源,一切都很好。

补充说明:

  • 注意初始化你的 Array的缓冲区,如果你需要 - m_pData = new T[m_nSize];将分配默认初始化的对象。如果这些对象没有默认构造函数,它们的值将是不确定的。一个简单的解决方法是使用 new T[m_nSize]{} ,它将执行值初始化——即将算术类型初始化为零,指向 nullptr 的指针, 和递归的复合类型。

  • 为您的类实现复制和/或移动语义,参见 Rule of three/five/zero .就像现在一样,复制 Array 的一个实例将导致两个实例认为它们拥有相同的缓冲区,并且当它们都尝试 delete 时会出现未定义的行为。

  • deletedelete检查空值,所以 if(m_pData != NULL)在析构函数中是多余的。

祝你好运:)

关于c++ - 模板化类中的析构函数实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40884250/

相关文章:

c++ - OpenGL + GLUT 聚光灯

c++ - 我怎么能给c++ vector赋值

Java从外部静态类创建类内的类数组

java - 类级别实例化与方法实例化之间的区别

c++ - 使用类而不是结构和构造函数问题

c++ - 如何根据另一个 vector 的排序对 vector 进行排序?

c++ - 对 TC++PL 第 4 版中的 Tuple 示例感到困惑

c++ - CPP 模板化成员函数特化

c++ - 如何在模板函数中为整数类型选择snprinf掩码?

c++ - 将指针 push_back 指向 vector 的正确方法