【问题标题】:Double free of child object after using the copy constructor使用复制构造函数后双释放子对象
【发布时间】:2018-11-19 12:42:51
【问题描述】:

我无法弄清楚为什么(看起来)一个对象被破坏了两次。

如果我创建了一个包含另一个类 (A) 的对象的类 (B) 的对象,并且我复制了这个对象。复制的对象被破坏两次。尽管它看起来像这样。我无法弄清楚这个输出。

我创建了以下(最少?)示例,这似乎引发了我的问题:

#include <stdio.h>
#include <stdint.h>

template <class T>
class A
{
public:
    A()
    {
        myCtr = ++ctr;
        printf("class A default Constructor - object id: %u\n", myCtr);
    }

    A(const A<T> &a2) {
        myCtr = ++ctr;
        printf("class A copy constructor - object id: %u\n", myCtr);

    }

    ~A()
    {
        printf("class A destructor - object id: %u\n", myCtr);
    }

    void add(T item) {
        /* Irrelevant */
    }

private:
    uint64_t myCtr;
    static uint64_t ctr;
};

class B
{
public:
    B() {

    }

    B(char * input, uint32_t len) {
        for (uint32_t i = 0; i < len; i++)
        {
            characters.add(input[i]);
        }
    }

    B(const B &b2) {
        characters = A<char>(b2.characters);
    }

    ~B() {

    }


private:
    A<char> characters;
};

template <class T>
uint64_t A<T>::ctr = 0;

int main(int argc, char *argv[]) {
    B b1 = B((char *)"b1", 2);
    B b2 = B(b1);

    return 0;
}

这会产生以下输出:

class A default Constructor - object id: 1
class A default Constructor - object id: 2
class A copy constructor - object id: 3
class A destructor - object id: 3
class A destructor - object id: 3
class A destructor - object id: 1

对象 id 3 被破坏了两次,而对象 id 2 根本没有被破坏。

我正在使用以下编译器: Microsoft (R) C/C++ 优化编译器版本 19.14.26429.4

如果您投反对票。请说明原因。我很乐意尝试改进我的问题。

【问题讨论】:

  • 注意characters = A&lt;char&gt;(b2.characters);拷贝赋值,是编译器自动生成的。

标签: c++ constructor destructor copy-constructor


【解决方案1】:

您需要关注rule of 5。如果你实现了一个重要的析构函数,复制/移动分配/构造,你必须实现所有 5 个,或者给出一个很好的理由为什么不这样做,或者删除它们。

您实现了 destory 和 copy ctor。您忽略了其他 3 个。添加它们。

还有更多characters = A&lt;char&gt;(b2.characters); 你的复制 ctor 调用复制分配。你不跟踪,这就是你的计数被关闭的原因。你在柜台分配。

【讨论】:

【解决方案2】:

混乱来自这一行。

characters = A<char>(b2.characters);

默认生成的赋值运算符将对象 3 复制到对象 2,包括 myCtr

myCtr 不是const,因此它可能会在其生命周期内发生变化。如果您需要一个值保持不变,请将其设为const

这是你的类的一个版本,它将按照你的预期行事。

template <class T>
class A
{
public:
    A()
        : myCtr( ++ctr )
    {
        printf("class A default Constructor - object id: %u\n", myCtr);
    }

    A(const A<T> &a2)
        : myCtr( ++ctr )
    {
        printf("class A copy constructor - object id: %u\n", myCtr);

    }

    A<T>& operator=(const A<T> &a2) {
        // Copy what's needed from a2 here.
        return *this;
    }

    ~A()
    {
        printf("class A destructor - object id: %u\n", myCtr);
    }

    void add(T item) {
        /* Irrelevant */
    }

private:
    const uint64_t myCtr;
    static uint64_t ctr;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2014-06-05
    相关资源
    最近更新 更多