复制构造函数......有什么问题?

时间:2012-04-21 15:40:49

标签: c++

所以我的问题是这个...当我试图为指针分配内存时,它会失败。

这是我的MatrixClass定义..

class MatrixClass
{
public:
    MatrixClass(int m, int n);
    MatrixClass(void);
    virtual ~MatrixClass(void);
    double getRead(int num1, int num2) const;
    double& getReadWrite(int num3, int num4);
    void set(int i,int j,double value);//set value at i,j to value
    MatrixClass(const MatrixClass &rhs);
    void assign(int M,int N);
    MatrixClass sum1(const MatrixClass& rhs) const;
    MatrixClass operator+(const MatrixClass& rhs);//overloading the + operator 
    MatrixClass operator-();
private:
    double* dataptr;
    int M;
    int N;
};

我想这样做..

MatrixClass BB;
BB = A + B;

所以这是我的重载+功能..

MatrixClass MatrixClass::operator +(const MatrixClass &rhs)
{
    MatrixClass temp;
    //temp.M = this->M + rhs.M;
    //temp.N = this->N + rhs.N;
    for(int i = 0;i < M;i++)
    {
        for(int j = 0; j<N;j++)
        {
            temp.dataptr[i * N + j] = this->getReadWrite(i,j) + rhs.dataptr[i*N+j];
        }
    }   
    return temp;
}//end operator +

一旦temp返回......它调用复制构造函数...将temp传递为'rhs'而'this'将引用'BB'? (我是否正确地想到这一点?)

MatrixClass::MatrixClass(const MatrixClass &rhs)//copy constructor
{
    this->M = rhs.M;
    this->N = rhs.N;
    dataptr = 0;
    if(rhs.dataptr != 0)
    {
        dataptr = new double[M * N];//allocate memory for the new object being assigned to...
        // the line here where I try to allocate memory gives me an error.....Am I right in
        //thinking that this would be assigning memory to dataptr of 'BB'?? Values are assigned to //'M' and 'N' fine....
        int num = sizeof(double);
        memcpy(this->dataptr,rhs.dataptr,M*N*sizeof(double));   
    }
    else
    {
        this->dataptr = 0;
    }
}//end copy constructor

我得到的错误是这个...'在assignment.exe中的0x75a0b727处未处理的异常:Microsoft C ++异常:std :: bad_alloc在内存位置0x002af924 ..'

所以基本上我要问的问题是..为什么到底是我试图在复制构造函数中为'dataptr'分配内存给我带来问题的行...这只是在调用复制构造函数时才这样做返回值'temp'..

谢谢!

2 个答案:

答案 0 :(得分:3)

简短回答:您尚未正确实施Rule of ThreeIn C++11, Rule of Five

答案很长:你没有实施operator=。编译器生成的一个对你的情况来说还不够。

除此之外,我的猜测是你的默认构造函数没有为dataptr分配内存。如果是这样,那么您在dataptr中使用operator+,甚至没有为其分配内存。这就是你的程序崩溃的原因。即使默认构造函数分配内存,问题仍然存在,因为rhs.Mrhs.N的值可能与您在默认构造函数中假设的值不同(正如您所说,{{1分别是}和4

因此,在5中为dataptr分配内存。此外,在分配之前,您必须释放它可能指向的内存,并且还需要将operator+M设置为Nrhs.M的值分别

答案 1 :(得分:1)

不,詹姆斯,你错了,当operator+返回拷贝构造函数时,将调用将局部变量temp转换为赋值运算符范围内的临时匿名对象。在复制构造函数中,this将引用此临时变量,而不是BB。

由于LHS已经存在,当operator+返回时它不会再“构建”,它将被“分配”,因此您需要重载operator=。 (有关更多详细信息,请参阅here。)默认operator=只是进行按位复制,因此如果不重载operator =,dataptr将被释放(我们希望)匿名临时对象的析构函数,当它超出范围(在复制后立即被销毁)时被销毁,而BB将指向释放的内存。你也会泄漏已经在BB中分配的任何内存,因为BB在被分配之前不会被销毁。 BB的dataptr会泄漏,而临时对象的dataptr将被释放两次。

所以,虽然你最终分配和复制内存三次很糟糕,为了让+和=在所有情况下工作,你需要做以下事情:

  • operator+中将MatrixClass temp;更改为MatrixClass temp(rhs.M, rhs.N);,以便temp.dataptr得到正确分配和解除分配。
  • 正如您所做的那样,在复制构造函数中为dataptr分配新内存并将其复制。
  • 重载operator=以便它首先检查自我分配(this == &rhs),如果它不是自我分配,则释放现有的dataptr,然后分配一个新的rhs并复制{ {1}}。