我不喜欢调试会话和内存指针粘贴的问题,但我不得不问这样的问题。 这是一个关于调用复制构造函数的问题。我知道已有答案,但我没有找到任何可以解决我的问题
我有一个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
并且我也有段错误。
任何暗示为什么会发生这种情况?或者有更好的方法来处理复制带副作用的对象?
答案 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 =。不要忘记检查自我任务。