我有一个表格
class A
{
int **a;
//other members
}
在某些函数中,我通过引用
传递A类的对象,比如obj
void func(A &o); //function declaration
和
func(std::ref(obj)); //function call
但是,我收到以下错误 - double free or corruption (!prev)
根据链接的问题,这是因为析构函数被多次调用指针成员,这是复制构造函数在复制时被多次调用的结果,导致尝试释放已经解除分配的内存。但是,当我通过引用传递完整的对象时,为什么会发生这种情况呢?不应该简单地复制整个对象的地址吗?
以上述链接和here中给出的形式实现复制构造函数的建议无济于事,因为它们涉及在复制对象时分配新的内存量,而我想传递对象,作为结果指针成员,通过引用。
我查看了this和this,可能重复,但他们没有解决我的问题。
基于其他一些答案,我也尝试将析构函数实现为
~A()
{
delete[] a;
}
或
~A()
{
if(a)
{
delete[] a;
}
}
但都没有解决问题。
答案 0 :(得分:2)
尝试A(A const&)=delete;
和A(A&&o):a(o.a){a=nullptr;}
。这将删除您的副本ctor并写入一个非分配移动ctor。
如果您尝试复制类的实例,则删除的副本ctor将为您提供编译时错误。在你的情况下,这会导致破坏时崩溃,这似乎是一个好主意。
移动ctor将允许您从函数中安全地返回类的实例,只要返回值是隐式或显式(std::move
)移动的。
还要考虑
A& operator=(A&&o) {
if (this==&o) return *this;
std::swap(a,o.a);
delete[] o.a;
o.a=nullptr;
return *this;
}
A& operator=(A const&o)=delete;
可让您从另一个移动的A
分配给A
。
当你编写析构函数时,你应该处理移动/复制赋值/构造的事实被称为五的规则。
你应该避免写任何一个这个事实被称为零规则。
为避免编写它们,请将a
替换为unique_ptr<int[]>
。现在它为您生成移动操作和析构函数,并自动删除您的复制操作。
答案 1 :(得分:0)
我解决了这个问题。我从一个函数返回了该类的对象,该函数调用了复制构造函数。我忽略了这个对象将按值传递的事实。
@IgorTandetnik的评论在一定程度上回答了这个问题,只要它确认我没有理由发现这个问题,除非我忽略了某个地方发生的价值传递。