赋值运算符创建指针,并且无法删除

Assignment operator creates pointer and doesn't make deleting possible

提问人:Frank Hansen 提问时间:2/15/2016 最后编辑:Frank Hansen 更新时间:2/15/2016 访问量:90

问:

作为学校作业的一部分,我们必须将一个抽象类装箱,并使用一个注册类来包含它们。抽象类有两个 under 类。 像动物>狗/猫

在这个任务中,我们必须创建一个赋值运算符,但在使用我所做的赋值运算符后,程序出现了问题。

我做两个寄存器

R1; R2;

然后使用运算符

r2 = r1;

当程序退出时,它会转到 R1 的 destruktor,将其删除,到达 R2 并获得“访问冲突读取位置”

我猜这是因为运算符创建了一个从 r2 到 r1 的指针,所以当 r1 被删除时。

算子:

Register& Register::operator=(Registerconst &other)
{
    for (int i = 0; i < this->count; i++)
    {
        delete this->animals[i];
    }
    delete[] this->animals;
    this->name = other.name;
    this->size = other.size;
    this->count = other.count;
    this->animals= new Animal*[this->size];
    for (int i = 0; i < this->count; i++)
    {
        animals[i] = other.animals[i];
    }
    for (int i = count; i < this->size; i++)
    {
        this->animals[i] = nullptr;
    }
    return *this;
}

析构函数不是虚拟的。不确定这是否导致了它

根据要求,这里是使用它的地方

AnimalRegister r1("Name 1");
AnimalRegister r2("Name 2");
// some stuff being added to r1
r2 = r1;
return 0;

构造函数:

AnimalRegister::AnimalRegister(string name)
{
    this->name = name;
    this->size = 10;
    this->count = 0;
    this->animals = new Animal*[this->size];
    for (int i = 0; i < this->size; i++)
        animals[i] = nullptr;
}

析构函数:

AnimalRegister::~AnimalRegister()
{
    for (int i = 0; i < this->count; i++)
        delete animals[i];
    delete[] animals;
}
C++ 析构函数 赋值运算符

评论

1赞 Cody Gray - on strike 2/15/2016
这只是我不知道的花哨的 OOP 术语吗?什么是“寄存器类”?
0赞 Lol4t0 2/15/2016
您想要的称为共享指针。如果您想自己制作,可以阅读实现详细信息部分以查找想法。
0赞 Lol4t0 2/15/2016
如果作业最初不是英文的,@CodyGray可能只是翻译问题
0赞 Frank Hansen 2/15/2016
对不起,由于名称,它被称为寄存器类,它有这些变量,并用作所有动物的寄存器:字符串名称;int 大小;int 计数;动物**动物;
0赞 Zereges 2/15/2016
寄存器类及其派生物的后析构函数。无论如何,析构函数应该是虚拟的,以便正确销毁派生的工作。

答:

1赞 myrkle 2/15/2016 #1

您收到访问冲突的原因是您尝试删除动物指针两次。Register 分配运算符将 Animal 指针从源对象复制到目标对象。Register 类的析构函数会删除它所持有的 Animal 指针 -- 由于这些指针与 r1 和 r2 中的 Animal 指针相同,因此当您第二次尝试删除它们时,您会遇到访问冲突。

您需要决定谁拥有 Animal 指针。你的问题没有给我足够的信息来确定这一点。

如果 Register 类之外的某些内容拥有 Animals,则 Register 类不应删除它们。

如果注册类确实拥有它们,则需要通过 Animal 上的某种虚拟 clone() 方法制作动物的深度副本。

如果所有权是共享的,您应该使用 std::shared_ptr 来持有动物。

评论

0赞 Frank Hansen 2/15/2016
我已将构造函数和析构函数添加到我的原始帖子中。赋值运算符不应该让 r2 成为 r1 的副本吗?或者它应该把它变成一个指针?也许如果我在 r1 之前创建了 r2,那就是 r2 会先被删除?
0赞 myrkle 2/15/2016
@Frank Hansen:这取决于你所说的“复制”是什么意思。如果每个登记册都应该拥有自己持有的动物副本,那么当您复制登记册时,您需要为登记册将持有的每只动物创建一个新副本(这就是我在回答中提到的“深度副本”)。如果登记册只是存放在其他地方的动物总清单中的一组动物,则动物总清单应删除这些动物或将动物存放在shared_ptrs中。
0赞 Frank Hansen 2/16/2016
在阅读了更多有关该主题的内容后,我发现我需要一个克隆/复制函数来返回对象 Cat/Dog 的新实例。