我们应该删除一个不是由我们使用new/malloc创建的指针吗?

6
class ClassA
{
public:
    ClassA(ClassB *p) b(p){}
    ~ClassA(){delete b;}
    ClassB *b;
};

这种设计是否好呢?

永远不要接受ClassA正在接管由*p指针给出的ClassB实例的情况。请仅返回翻译后的文本内容,不要进行解释。 - erjot
7个回答

9
答案是“要看情况”。您必须明确谁负责对象的生命周期。
此外,ClassA缺少用户定义的复制构造函数和赋值运算符,这可能导致未定义的行为。例如:
ClassA object1( new ClassB() ); //object1 takes ownership of the object
ClassA object2( object1 ); //object2 takes ownership of the same object
// now first object2 is destroyed and deletes the object
// then object1 is destroyed and double-delete happens

因此你的例子可能不是一个很好的例子。

2

您的意思是:

class ClassA  { 
  ClassB *b;  
public: 
  ClassA(ClassB * p) {b = p;} 
  ~ClassA() {delete b;}  
};

这不是一个好的设计。创建者应该是删除者。


1
通常在这种情况下使用指针是不好的设计。在这种情况下,智能指针是您最好的朋友。但是如果您必须使用指针,则只需选择其中一种方式并仔细记录即可。

1

从技术上讲,这并没有什么特别的问题 - 当创建ClassB实例时(即在需要ClassA之前),您已经将其所有权传递给了ClassA实例(但一旦创建了ClassA,则它将成为ClassB的所有者)。

它是否是一个好的设计,取决于它所应用的上下文。例如,ClassA接管ClassB是否有意义?是否应该使用智能指针而不是“普通的”指针?


1

正如其他人所说,最好通过使用智能指针或在创建对象的同一级别上删除对象来避免这种情况...或者根本不使用指针。

同时,我不认为转移对象所有权一定是不良设计,只要在文档中明确告知ClassA用户即可。在编写函数时,我遇到了类似的情况,这些函数接受一个指向对象的指针并对其进行复制构造以供自己使用。在需要的情况下,我倾向于使用“参数复制语义”之类的注释来告诉调用者“我返回后你可以随意处理这个对象...我有自己的副本”。

如果您正在使用裸指针,则考虑建立这些调用者合同非常重要。


0
通常情况下,这是一种令人困惑/不一致的设计(通常希望相应的newdelete在同一级别上发生)。然而,也有一些例外情况;例如,智能指针提供了一个原始指针,然后接管对象的所有权,因此它们负责在不再需要时调用delete

0
一般来说,这是一个不好的想法。很多时候,你并不知道ClassB对象是如何创建的。它可能是一个指向使用new[]运算符创建的数组元素的指针,或者它可能是从使用自定义内存分配器的独立dll中传递给你的。在这些情况下,使用operator delete来释放这个指针将是一个严重的错误。

通常情况下,这个API的用户只使用一个ClassB*参数,它可以通过new创建,也可以是一个ClassB元素的地址。在后一种情况下,这将导致双重释放。 - qiuxiafei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接