复制构造函数未被调用(再次)

时间:2011-10-22 12:44:53

标签: c++ copy-constructor

我不喜欢调试会话和内存指针粘贴的问题,但我不得不问这样的问题。 这是一个关于调用复制构造函数的问题。我知道已有答案,但我没有找到任何可以解决我的问题

我有一个Matrix类:

class Matrix {
    ...

    Matrix(const Matrix& other); // copy constructor, needed due to *data

    private:
    int *data;
};

Matrix包含指向静态内存数组data的指针,因此当我复制Matrix时,静态数组也应该与mempy一起复制。

有一次,我想将Matrix对象复制到另一个Matrix

debug("COPY BEGIN ");
debug("matricex before copy: " << &itsMatrix << " < " << &matrix);
itsMatrix = matrix;
debug("COPY END ");
debug("matricex after copy: " << &itsMatrix << " < " << &matrix);

应该调用复制构造函数来复制data。显然,不是调用构造函数,而是只复制指针的 values ;之后当两个内存矩阵都被删除时,指向data指针被删除两次而且我有段错误

这是一个调试会话:

1: Matrix.cpp MATRUX EMPTY 0xbf901a28 with empty data 0
2: include/SubArrayMax.hpp COPY BEGIN 
3: include/SubArrayMax.hpp matricex before copy: 0xbf901a28 < 0xbf901a3c
     --- here I should see a copy constructor ---
     --- but no debug string is printed ---
4: include/SubArrayMax.hpp COPY END 
5: include/SubArrayMax.hpp matricex after copy: 0xbf901a28 < 0xbf901a3c
6: Matrix.cpp DELETE MATRIX 0xbf901a28 with data 0x81d0550
7: Matrix.cpp DELETE MATRIX 0xbf901a3c with data 0x81d0550
 --- 0x81d0550 is deleted twice ---

这是我的复制构造函数:

Matrix::Matrix(const Matrix& other) // copy construcutor
{
    ...
    data = new mval_t[dim.w * dim.h];
    memcpy(data, other.data, dim.w * dim.h * sizeof(mval_t));
    debug("MATRIX " << this << " after copying, data " << data);
}

我知道复制构造函数可以通过编译器来减少,我尝试-fno-elide-constructors并且我也有段错误。

任何暗示为什么会发生这种情况?或者有更好的方法来处理复制带副作用的对象?

2 个答案:

答案 0 :(得分:2)

不,在您的情况下,将调用赋值运算符。

只需定义

Matrix& operator=(const Matrix& other);

...

Matrix& Matrix::operator=(const Matrix& other) // overloaded assignment
{
    if (this != &other) // self-assignment is usually a problem, avoid it
    {
        ...
        // Stage 1: Do all dangerous stuff that can throw.
        int* tmp = new mval_t[dim.w * dim.h];
        memcpy(tmp, other.data, dim.w * dim.h * sizeof(mval_t)); 
        // In this case the copy is safe, but for memory allocation
        // can throw
        // If you need to allocate several things, perhaps it's better
        // to use std::nothrow and check the result, otherwise
        // throwing on the second allocation would leak the first one

        // Stage 2: Do a safe swap.
        //    Because there is no chance of an exception now we can mutate the object
        //    in an atomic way.
        std::swap(tmp, data)

        // Stage 3: Release any old resource.
        delete tmp;            
    }
    return *this;
}

答案 1 :(得分:2)

示例代码段中的行不会导致调用复制构造函数。它将使用operator =,由于您获得的行为与默认的浅拷贝匹配,因此可能未实现。 尝试使用与复制构造函数类似的逻辑实现operator =。不要忘记检查自我任务。