C ++类析构函数如果“所有者”删除成员?

问题描述 投票:0回答:1

我在C ++中知道指针就是:指向内存位置的指针,并没有“所有者”的概念。但请考虑以下情况(不一定是好的代码):

class A {
public:
    A(){}
    ~A()
    { if(myObject!=nullptr)
        delete myObject;
    }

    void createMember()
    {myObject=new CrazyCustomClass();}

    CrazyCustomClass *getMember()
    {return myObject;}
private:
    CrazyCustomClass *myObject=nullptr;
}

如果它有所不同,CrazyCustomClass没有复制构造函数,因为复制它是没有意义的。非常直接 - 我有一个类,在实例化后的某个时刻,可以调用new来实例化CrazyCustomClass *类型的成员

问题是,如果在某些时候我有一个class A副本创建(这很好 - 我希望能够复制class A)。删除该副本时,原始类A实例化指向的对象也是如此。例如:

void StupidFunction(A *firstObject){
//This is NOT a real function, it simply illustrates the effect of a third-party library function
    //create a new object that is a copy of first object
    A secondObject(*firstObject);
    <do whatever with second object>
    //secondObject goes out of scope here and gets deleted.
}

A *firstObject=new A();
firstObject->createMember();
stupidFunction(firstObject);
CrazyCustomClass *customObject=firstObject.getMember(); //this is now an invalid pointer

在上面的例子中,StupidFunction来自第三方库,其想法是它提供了一个可以使用的对象的“临时”副本,而不会弄乱原始对象,这很好。 Class ACrazyCustomClass都是我的代码,可以随意更改。不幸的是,当删除“临时”副本时,我编写析构函数的方式会导致问题。

我的第一个想法是使用shared_ptr,如下所示:

std::shared_ptr<CrazyCustomClass> sharedObject=std::make_shared<CrazyCustomClass>(new CrazyCustomClass);

...但编译时这给了我一个错误:

候选构造函数(隐式复制构造函数)不可行:第一个参数没有从'CrazyCustomClass *'到'const CrazyCustomClass'的已知转换;用*取消引用参数

如果我用*取消引用参数,它会给我一个关于被删除的"CrazyCustomClass"的复制构造函数的错误,这是真的 - 没有合理的方法来复制CrazyCustomClass

所以我的问题是:如何重构class A,以便myObjectfirstObject超出范围时被正确删除,但是当A的任何“临时”副本被删除时不能?

c++ reference-counting
1个回答
0
投票

使用shared_ptr实际上是解决这个问题的方法,但是在原始问题中尝试的代码是不正确的。有两种(至少)不同的方法来初始化shared_ptr(参考:https://msdn.microsoft.com/en-us/library/hh279669.aspx)。首先,您可以使用new作为构造函数参数来执行此操作:

shared_ptr<CrazyCustomClass> myObject(new CrazyCustomClass)

其次,这是一般首选的方法,你可以使用make_shared函数(在原始帖子中尝试),它不是new对象,而是传递给对象构造函数的参数,在这种情况下没有:

shared_ptr<CrazyCustomClass> myObject=make_shared<CrazyCustomClass>()

原始代码只是混淆了这两个方法,因此有关复制构造函数的错误:它试图用指向CrazyCustomClass对象的指针作为构造函数参数来实例化一个新的CrazyCustomClass对象。

一旦使用shared_ptr,必须删除析构函数中的delete

给@tkausl和@alterigel的帽子提示,指出问题评论中的错误!

© www.soinside.com 2019 - 2024. All rights reserved.