Конструктор копирования не вызывается (снова) - PullRequest
0 голосов
/ 22 октября 2011

Мне не нравятся вопросы с отладочными сеансами и вставленными указателями памяти, но я вынужден задавать один такой.Это вопрос о вызове конструкторов копирования.Я знаю, что уже есть ответы на этот вопрос, но я не нашел ничего, что решило бы мою проблему

У меня есть класс Matrix:

class Matrix {
    ...

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

    private:
    int *data;
};

Matrix содержит указатель на статическую памятьмассив data, поэтому, когда я копирую матрицу, статический массив также должен быть скопирован с mempy.

. В какой-то момент я хочу скопировать объект матрицы в другую матрицу

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

Конструктор копирования должен быть вызван для копирования data.По-видимому, вместо вызова конструктора копируются только значения указателей;позже, когда обе матрицы памяти удалены, один и тот же указатель на data удаляется дважды, и у меня возникает ошибка seg

Вот сеанс отладки:

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, и у меня также была ошибка seg.

Любой намек, почему это происходит?или, может быть, есть лучший способ справиться с копированием объектов с побочными эффектами?

Ответы [ 2 ]

2 голосов
/ 22 октября 2011

Строка в вашем примере фрагмента не будет вызывать конструктор копирования. Он будет использовать оператор =, который, вероятно, не был реализован, так как поведение, которое вы получаете, соответствует типовой мелкой копии. Попробуйте реализовать operator = с логикой, аналогичной вашему конструктору копирования Не забудьте проверить самопредставление.

2 голосов
/ 22 октября 2011

Нет, в вашем случае будет вызван оператор присваивания.

Просто определите

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;
}
...