C ++类析构函数删除成员是否为“所有者”?

时间:2018-08-30 19:00:13

标签: c++ reference-counting

我在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)。当该 copy 被删除时,原始类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”的已知转换   第一个论点;用*

取消引用参数

并且如果我 do 用*取消引用参数,则会给我一个有关删除"CrazyCustomClass"的复制构造函数的错误,这是正确的-没有明智的复制方法{ {1}}。

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

1 个答案:

答案 0 :(得分:0)

实际上,使用AudioEnginePlayer.sharedInstance.audioQueue.async { if !self.isPlaying { self.volume = 1.0 self.audioFile.framePosition = frameCount.startingFrame self.prepare(withFrameCount: frameCount.frameCount) self.play(at: AudioEnginePlayer.sharedInstance.loopMsLastStartRenderTime) //Calculated lastRenderTime } self.scheduleSegment(self.audioFile, startingFrame: frameCount.startingFrame, frameCount: frameCount.frameCount, at: nil) { //WARNING: COMPLETION HANDLER RUNNING EARLY THEN FILE IS COMPLETED if self.isStopPressed == false { //Run fileEndCompletion only when player seek to end. fileEndCompletionHandler() if loop { self.playAudioFile(loop: loop, startTime: 0, fileEndCompletionHandler: fileEndCompletionHandler) } } } } 可以解决此问题,但是原始问题中尝试的代码不正确。有两种(至少)不同的初始化shared_ptr的方式(参考:https://msdn.microsoft.com/en-us/library/hh279669.aspx)。首先,您可以使用shared_ptr作为构造函数参数来实现它:

new

第二,这是通常首选的方法,您可以使用make_shared函数(如原始文章中所述),该函数不使用shared_ptr<CrazyCustomClass> myObject(new CrazyCustomClass) 对象,而是使用 arguments 传递给对象构造函数,在这种情况下什么也没有:

new

原始代码只是将这两种方法混合在一起,因此产生了有关复制构造函数的错误:它试图实例化一个新的shared_ptr<CrazyCustomClass> myObject=make_shared<CrazyCustomClass>() 对象,并使用一个指向CrazyCustomClass对象的指针作为构造函数参数。

使用CrazyCustomClass后,必须删除析构函数中的shared_ptr

@tkausl和@alterigel指出了问题注释中的错误!