【问题标题】:deletion of pointer that is a public class member删除作为公共类成员的指针
【发布时间】:2013-04-02 11:10:38
【问题描述】:

我有一个结构/类,其成员是指针,比如说

struct myStruc
{
    int* m_p;
}

1.问题: 我应该在哪里删除指针?在析构函数中?

myStruct::~myStruct()
{
    delete m_p;
}

2。问题:如果将指针分配给指针数组会怎样,例如

myStruct mS;
mS.m_p = new int[3];

如果我必须做deletedelete[],现在有没有好的方法(没有dynamic_cast 或try-catch)?

【问题讨论】:

  • A/方式是在构造函数中分配内存,在析构函数中释放内存。
  • 您能详细介绍一下用例吗? myStruc 的目的是什么?谁在设置 m_p? m_p 指向什么?谁决定并知道这一点?
  • @DaveRager 虽然这是一个很好的一般建议,但struct 通常只是一个没有太多附加功能的数据集合,这些数据使用public,因为应该不需要太多封装。至少当我看到一个类被定义为struct时,我是这么理解的。

标签: c++ pointers


【解决方案1】:

你不应该让“用户”在你的数据结构中弄乱指针。将指针设为私有并使用 get/set 函数来访问它。

所以:

struct myStruc
{
  private:
    int* m_p;
  public:
    int* ptr() { return m_p; }
    void allocate(int n) { m_p = new int[n]; 
    myStruc() : m_p(0) {};
    ~myStruc() { delete [] m_p; }
};

编辑:上面的类不完整,它显示了概念。对于一个完整的类,您需要一个复制构造函数和一个赋值运算符,并且可能从 allocate 函数中“记住”n

现在您不必担心是否使用 [] 进行分配,因为它是一致的。

当然,您可以使用std::vector 来实现这一点,而无需任何额外的努力。

【讨论】:

  • 您的代码有问题。它不遵循三法则。这是一场等待发生的灾难。
  • @AlokSave:你到底指的是什么?缺少复制构造函数?
  • @ezdazuzena:是的。在这种情况下,无论何时复制对象,都会使用隐式生成的复制构造函数,并且它不会对您的数据成员进行深层复制。这基本上意味着您最终会得到两个对象,它们引用相同的动态分配的内存,一旦其中一个超出范围,它就会释放内存并为您提供一个悬空指针和 UB。可以说该类不可复制或可赋值,但复制构造函数和赋值运算符都应声明为private,并且不应提供任何定义。
  • 添加编辑以解释它“不完整”。
【解决方案2】:

理想情况下,您根本不应该使用原始指针成员。你有两个更好的选择:

  1. 使用std::vector
  2. 使用智能指针作为成员和choose the right one as per your usage semantic

如果你不能使用智能指针而必须使用原始指针,那么:

  • 如果使用new分配指针,则使用delete,如果使用new [],则需要使用delete []。不应该有不匹配。
  • 每次动态分配成员的生命周期结束时,您都需要调用deletedelete []。假设这个成员的生命周期与你的类的生命周期相同,它将在析构函数中。
  • 重要的是你应该关注The Rule of Three

【讨论】:

  • @ezdazuzena:你不需要提升。 std::vector 是自 C++03 以来语言的一部分,而如果您使用的是 C++11,则有多种智能指针可供您选择。
  • 我同意这个答案。如果我们假设该类已正确定义为struct,那么说指针不应该是public 就错过了这里的重点。
【解决方案3】:
  1. 理想的析构函数。但请关注Rule of Three
  2. 您应该使用delete[]new/new[] 应分别使用delete/delte[]

【讨论】:

  • 关于 2.:我现在如何使用新的 int[3]?如果执行mS.m_p = new int(); 会怎样? delete[] 会失败。
  • 为什么最好在析构函数中?结构如何知道它是否应该删除指针,或者是否调用deletedelete[]
  • @juanchopanza 从我的角度来看,原始指针通常在析构函数中返回它的资源。我在2中回答了您评论的删除部分。
  • 析构函数无法知道是否使用了new[]new
  • @juanchopanza 如果我的陈述模棱两可,我很抱歉。返回获取的资源是程序员的责任。我在 2 中要说的是,如果程序员使用 new/new[] 获取了资源,则必须使用相应的 delete/delete[]。
猜你喜欢
  • 1970-01-01
  • 2013-06-14
  • 2012-03-18
  • 1970-01-01
  • 2020-06-19
  • 2013-12-30
  • 2013-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多