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

发布于 2024-12-11 11:38:28 字数 1820 浏览 0 评论 0原文

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

我有一个 Matrix 类:

class Matrix {
    ...

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

    private:
    int *data;
};

Matrix 包含一个指向静态内存数组 data 的指针,所以当我复制一个矩阵,静态数组也应该用mempy复制。

在某一时刻,我想将 Matrix 对象复制到另一个 Matrix。

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

应该调用复制构造函数来复制数据。显然,不是调用构造函数,而是仅复制指针的值;稍后,当两个内存矩阵都被删除时,同一个指向数据的指针被删除两次,并且出现段错误

这是一个调试会话:

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 错误。

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

I don't like questions with debug sessions and memory pointers pasted, but I am forced to ask one like that.
This is a question about invoking copy constructors. I know there are already answers about that, but I didn't find anything that would solve my problem

I have a Matrix class:

class Matrix {
    ...

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

    private:
    int *data;
};

Matrix contains a pointer to a static memory array data, so when I copy a Matrix, the static array should be also copied with mempy.

At one point, I want to copy Matrix object to another Matrix

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

The copy constructor should be invoked to copy the data. Apparently, instead of invoking the constructor, only values of the pointers are copied; later when both memory matrices are deleted, the same pointer to data is deleted twice and I have seg fault

Here is a debug session:

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 ---

and this is my copy constructor:

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

I know that copy constructors can be reduced by compiler, I tried -fno-elide-constructors and I also had seg fault.

Any hint why this happens? or maybe there is a better way to deal with copying objects with side effects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深白境迁sunset 2024-12-18 11:38:28

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

只需定义

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

No, in your case the assignment operator will be called.

Just define

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;
}
静谧幽蓝 2024-12-18 11:38:28

示例代码片段中的行不会导致调用复制构造函数。它将使用运算符=,这可能没有实现,因为您获得的行为与默认的浅拷贝匹配。
尝试使用与复制构造函数类似的逻辑来实现运算符=。不过,不要忘记检查自我分配。

The line in your sample snippet will not cause the copy constructor to be called. It will use operator = which probably wasn't implemented since the behavior you are getting matches the default shallow copy.
Try implementing operator = with similar logic to your copy constructor. Don't forget to check for self assignment though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文