【问题标题】:why calling assignment operator triggers destruction function?为什么调用赋值运算符会触发销毁函数?
【发布时间】:2013-07-24 04:05:08
【问题描述】:

我有一个名为 Matrix 的类,它带有二维指针 bool** 矩阵。

看看这段代码:

void Matrix::operator=(const Matrix& A){ 

    cout << "address in A : " << A.matrix << endl ;
    cout << "address in y : " << matrix << endl ;

    //return *this;
}

我在我的主函数中这样调用了 = 运算符:

Matrix x(3,5);
Matrix y(3,5);

x.set(1,4,1);
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;
y = x;
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;

析构函数是这样的:

Matrix::~Matrix(){
    cout << "address de : " << matrix <<endl;
    for (int i=0;i<m;i++)
        delete[] matrix[i];
    delete[] matrix;
    cout << "address de finish : " << matrix <<endl;
}

当我在 xcode 中运行我的程序时,我得到:

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address de : 0x100103ab0
address de finish : 0x100103ab0

它看起来不错,但是当我像这样更改 = 运算符函数时:

Matrix Matrix::operator=(const Matrix& A){

    cout << "address in A : " << A.matrix << endl ;
    cout << "address in y : " << matrix << endl ;

    return *this;
}

我得到这个结果:

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
Thesis(26190) malloc: *** error for object 0x100103b10: pointer being freed was not allocated

谁能向我解释为什么析构函数在后一个代码中触发得更快?!以及如何预防

提前谢谢你

【问题讨论】:

  • 您能否发布您的班级声明以及填充(初始化)您的对象的代码?
  • 快速建议:扔掉所有这些,并在std::vector 周围编写一个简单的包装器。写整个东西可能比修复你现在拥有的东西要少。
  • Mark B 的回答是正确的,但是如果您遇到该错误,则说明您还有其他问题,很可能是在您的复制构造函数中,我猜您没有编写。

标签: c++ destructor equals-operator


【解决方案1】:

原因是您修改后的复制赋值运算符返回按值,它创建矩阵的副本,返回它,然后销毁它。

复制赋值运算符的规范签名是 Matrix&amp; Matrix::operator=(const Matrix&amp; A)(请注意,我是通过非常量引用返回的)。

编辑:请记住,如果您只使用vector,所有这些内存管理都会消失,所有这些函数都可以使用编译器默认值。尽管如果您实际上将 bools 存储在矩阵中,vector&lt;bool&gt; 是专门化的,您应该确保了解该专门化如何与您的代码交互。

【讨论】:

  • 听起来他也在使用默认的复制构造函数,它复制指针的值,而不是复制数据。
  • 感谢您的快速回复,您是对的,我将 = 运算符函数更改为返回引用,它就像一个魅力。最后一个问题:我将在 Windows 或 linux 等其他操作系统上使用和编译此代码。是其他编译器中的vector类标准吗?
【解决方案2】:

您的赋值运算符按值返回*this,并对其进行复制。通常,您会返回一个参考:

Matrix& Matrix::operator=(const Matrix& A)
//    ^

复制是使用隐式复制构造函数进行的,它只是复制成员指针。您现在有两个对象,它们都认为它们“拥有”分配的内存。 operator=返回的临时值很快被销毁,删除内存,留下y一个悬空指针;当y 再次尝试删除相同的内存时,您会收到错误消息。

这就是为什么管理资源的类应该遵循Rule of Three,以确保它们可以安全复制。 std::vector 等标准容器就是这样做的;使用这些而不是自己管理内存通常是个好主意。

【讨论】:

    猜你喜欢
    • 2011-05-21
    • 1970-01-01
    • 2016-07-25
    • 2017-10-11
    • 2019-02-05
    • 2020-02-05
    • 2020-11-22
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多