标量删除析构函数问题 [英] scalar deleting destructor issue

查看:114
本文介绍了标量删除析构函数问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道为什么下面的代码会出错。

I can't figure out why I get error for the code below.

对象A的实例将被放入向量 vectorA.push_back(A a))连续。因此,有时需要重新分配 vectorA ;将调用析构函数,这是调用 A 的析构函数的位置,然后出现错误消息。

The instances of object A will be pushed into a vector (vectorA.push_back(A a)) continuously. So sometimes, vectorA needs to be reallocated; the destructor will be called, which is where the destructor of A gets called, then the error message appears.

class A
{
    long filePos;

    union {
        Recording* recording;
        UINT64 timeStamp;
    };

public:
    inline A(long fpos, UINT64 ts) : filePos(fpos), timeStamp(ts) {}
    ~A()
    {
        if (getDetailedType() == RECORDING_TYPE)
            if (recording)
                delete recording; // error: scalar deleting destructor ???
    }

    inline short getDetailedType() const { return (short)(timeStamp % 5); }
    A(const A& edi)
    {
        filePos = edi.filePos;

        if (getDetailedType() == RECORDING_INFO)
            recording = edi.recording;
        else
            timeStamp = edi.timeStamp;
    }

}

class Recording : protected RECORDINGS
{
    UINT64 timestamp;
    float scalar;

public:
    ~Recording() // with or without this dtor, got same error
    {
    }

    inline Recording()
    {
        timestamp = 0;
        scalar = 2.0;
        time = 0;
        rate = 30;
        type = 1;
        side = 1;
    }
}

typedef struct
{
    UINT32 time;
    float rate;
    int type;
    int side;

} RECORDINGS;


推荐答案

您的副本构造函数执行浅表副本。因此,现在您有了两个对象,它们都具有相同的 recording 指针。

Your copy constructor does a shallow copy. So, now you have two objects that both have the same recording pointer.

您应该做一个深拷贝,或确保所有权被正确转移(通过使用诸如 std :: unique_ptr< Recording>之类的东西如果 C ++ 11 可用。

You should either do a deep copy, or ensure the ownership is properly transferred (by using something like std::unique_ptr<Recording> if C++11 is available.

请参见有关深层副本和浅层副本之间差异的问题。

我们来看一些示例:

class ABadCopyingClass
{
public:
   ABadCopyingClass()
   {
       a_ = new int(5);
   }

   ~ABadCopyingClass()
   {
       delete a_;
   }

private:
    int* a_;   
};

上面的类是不好的,因为默认的复制构造函数和赋值运算符将执行浅表复制,并导致两个对象都认为自己拥有底层 a _ 对象。当其中之一消失时范围内, a _ 将被删除,而另一个指针将悬空,最终导致崩溃。

The above class is bad because the default copy constructor and assignment operator will perform a shallow copy, and lead to two objects both thinking that they own the underlying a_ object. When one of them goes out of scope, the a_ will be deleted, and the other one will be left with a dangling pointer that will eventually lead to a crash.

class ABetterCopyingClass
{
public:
    ABetterCopyingClass()
       a_(new int(5))
    {
    }

    ABetterCopyingClass(const ABetterCopyingClass& r)
    {
        a_ = new int(*r.a_);
    }

    ABetterCopyingClass& operator=(const ABetterCopyingClass& r)
    {
        // in the case of reassignment...
        delete a_;

        a_ = new int(*r.a_);
        return *this;
    }

    ~ABetterCopyingClass()
    {
        delete a_;
    }

private:
    int* a_;    

};

该类对我们的情况有所改善(请注意,在这种简单的方法中没有进行常规的错误检查例)。现在,复制构造函数和赋值运算符可以正确执行必要的深度复制。这里的缺点是我们必须添加大量样板代码-很容易出错。

This class improved our situation a little (note, that the normal error checking is left out in this simple example). Now the copy constructor and assignment operator properly perform the necessary deep copying. The drawback here is the amount of boilerplate code we had to add -- it's easy to get that wrong.

class ACannonicalCopyingClass
{
public:
   ACannonicalCopyingClass()
      : a_(new int(5))
   {
   }

   ACannonicalCopyingClass(ACannonicalCopyingClass&& moved_from)
   {
       a_ = std::move(moved_from.a_);
   }
private:
   std::unique_ptr<int> a_;
};

此示例(仅C ++ 11)更好。我们删除了大量的样板代码,但是这里的语义有些不同。在这种情况下,我们无需转移深层复制,而是转移了基础 a _ 对象的所有权。

This example (C++11 only) is even better. We've removed a significant amount of boilerplate code, however the semantics here are a bit different. Instead of deep copying, we get in this case transfer of ownership of the underlying a_ object.

最简单的版本(仅C ++ 11)要实现的版本提供了基础 a _ 对象的共享所有权。这是与您提供的示例最相似的版本,并附加了不会导致崩溃的奖励。

The easiest version (C++11 only) to implement is the version that provides shared ownership of the underlying a_ object. This is the version that is most similar to your provided example, with the added bonus that it does not cause a crash.

class ASharedCopyingClass
{
public:
   ASharedCopyingClass()
      : a_(std::make_shared<int>(5))
   {
   }

private:
    std::shared_ptr<int> a_;
};

此版本可以随意复制,底层的 a _ 对象将很高兴被引用计数。最后一个超出范围的副本会将引用计数设置为 0 ,这将触发内存释放。

This version can be copied at will, and the underlying a_ object will happily be reference counted. The last copy to go out of scope will set the reference count to 0, which will trigger the memory deallocation.

这篇关于标量删除析构函数问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆