简体   繁体   English

C ++如何使用破坏状态的析构函数处理对象的副本?

[英]C++ How to handle copy of objects with destructor that damages the state?

I'm not sure if I've worded this correctly. 我不确定我的措词是否正确。

Basically, I have a class like this: 基本上,我有一个这样的课:

class A
{
public:
    A()
    {
        CreateHandle(&m_handle);
    }

    ~A() 
    { 
        DeleteHandle(&m_handle); 
    }

private:
    Handle m_handle;
}

And it's a member of another class: 它是另一个类的成员:

class B
{
public:
    B(int data) : m_data(data) {} 
    /* ... */

private:
    A m_a;
    int m_data;
}

And finally I have a third class which is sort of like a container of B s: 最后,我有了第三类,有点像B的容器:

class C
{
public:
    /* ... */
    void AddOneB(B b)
    {
        m_bs.push_back(b);
    }        

private:
    std::vector<B> m_bs;
}

Lastly, in my code where I'm creating a C instance, I would do something like this: 最后,在创建C实例的代码中,我将执行以下操作:

...
C cObj;
cObj.AddOneB( B(23) );
...

My problem is that the destructor of A actually destroys the memory that it created in it's constructor. 我的问题是A的析构函数实际上破坏了它在其构造函数中创建的内存。 So doing this results in my cObj getting a B with an A that it no good. 因此,这样做会导致我的cObj得到一个B和一个A ,这不好。

My first thought was to make the instance of A in B a std::shared_ptr , but I was wondering if there's any other, paradigm (is that the word), to handle situations like this? 我的第一个想法是将BA实例设为std::shared_ptr ,但是我想知道是否还有其他范式(就是这个词)来处理这种情况?

I can't see how copy constructors or move constructors can help here because the destructor will be called regardless. 我看不到复制构造函数或移动构造函数在这里有什么帮助,因为无论如何都会调用析构函数。

You need to make a choice: either A has unique ownership of the Handle , or it has shared ownership of it. 您需要做出选择: A拥有Handle 唯一所有权 ,或者它拥有它的共享所有权

If the former, you need to make A noncopyable. 如果是前者,则需要使A不可复制。 For exactly the problems you present in your question. 对于问题中出现的问题。 If C++11, you should make it movable: 如果是C ++ 11,则应使其可移动:

A(const A&) = delete;
A& operator=(const A&) = delete;

A(A&& rhs) {
   // transfer ownership of m_handle from rhs to this
   // so that rhs doesn't destroy it
}

If the latter, you need to reference count the Handle so that only one of the copies of A destroys it: 如果是后者,则需要引用该Handle以便仅A一个副本销毁它:

class A {
    int* refCnt;
    Handle m_handle;

public:
    A()
    {
        CreateHandle(&m_handle);
        refCnt = new int(1);
    }

    A(const A& rhs)
    : m_handle(rhs.m_handle)
    , refCnt(rhs.refCnt)
    {
        (*refCnt)++; // now we have an additional reference
    }

    ~A() {
        if (--*refCnt == 0) {
            // only destroy if we're the LAST one
            DeleteHandle(&m_handle);
        }
    }
};

Shared ownership is more expensive (and what I wrote above is not thread-safe, if that's a concern), so pick the one that makes the most definitely. 共享所有权更加昂贵(如果担心的话,我上面写的也不是线程安全的),因此请选择最确定的所有权。 Definitely you cannot have a copyable type that expresses have unique ownership - that is asking for trouble. 绝对不能拥有表示唯一所有权的可复制类型-这很麻烦。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM