0

I have got some trouble in learning c++. The code below I can complie, but run crash when i debug (the picture I poste), but I can find the true problem of the code. The compile tools I use is dev++.

The doubt point is memcpy(array,ar.getArray(),r*c*sizeof(array[0][0])); because some guy tell me it is shallow copy not deep copy, in fact, what I want to do is to copy the value not the address.

Erorr: enter image description here

Code:

#include<iostream>
#include<cstdlib>
using namespace std;
class Array2 {
    
    private:
        int r;
        int c;
        int **array;
    public:
        Array2 (){
            cout<<"no character constructor"<<endl;
            //k=1;
        }
        Array2 (int row,int colume);  
        ~Array2()
        {
            if(array)
            {               
                cout<<"deconstructor called!"<<endl;
                for(int i=0;i<r;++i)
                {
                    delete [] array[i];
                }
                delete [] array;
                                
            } 
    
        }
        int * operator [] (int & i);
        int & operator () (int & i,int & j); 
        Array2 & operator = ( Array2 & ar);

        void setR(int row){
            r=row;
        }
        void setC(int colume){
            c=colume;
        }
                
        int getR()  {
            return r;
        }
        int getC()  {
            return c;
        }
        int** getArray()    {
            return array;
        }                           
};
Array2 & Array2::  operator = ( Array2 & ar){   
    cout<<"= character constructor"<<endl;
    r=ar.getC();
    c=ar.getR();
    array=new int*[r*c];
    for(int i=0;i<r;i++){
        array[i]=new int[c];
    }
    memcpy(array,ar.getArray(),r*c*sizeof(array[0][0]));    
    return *this;   
}

int & Array2:: operator () (int & i,int & j){
    return array[i][j];
}   

int *  Array2:: operator [] (int & i){
    //return a[i];
    return array[i];
}


Array2:: Array2(int row,int colume ):r(row),c(colume)
{   
    cout<<" character constructor"<<endl;
    array=new int*[r];
    for(int i=0;i<r;i++){
        array[i]=new int[c];
    }
    
}
int main()
{
    Array2 a(3,4);
    int i,j;
    for(i=0;i<3;++i)
    {
        for(j=0;j<4;j++)
        {
            a[i][j]=i*4+j;
        }
    }
    for(i=0;i<3;++i)
    {
        for(j=0;j<4;++j)
            cout<<a(i,j)<<",";
        cout<<endl;
    }
    cout<<"next"<<endl; 

    Array2 b;
    Array2 c(3,4);
    b=a;
    for(i=0;i<3;++i)
    {
        for(j=0;j<4;++j)
            cout<<b(i,j)<<",";
    cout<<endl;
    }   
    
    if(&a==&b)
        cout<<"a and b adress is the same"<<endl;
    else
    {
        cout<<"a and b adress is not the same"<<endl;
        cout<<"a:"<<a.getArray()<<","<<"b:"<<b.getArray()<<endl;        
    }

    if(&a!=&c)
        cout<<"a and c adress is not the same"<<endl;
    cout<<"a:"<<a.getArray()<<","<<"c:"<<c.getArray()<<endl;
    return 0;   
}
TheSmith1222
  • 345
  • 1
  • 4
  • 11
  • Refer to [rule of three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) and avoid using `new`. Instead use smart pointers wherever possible. – Jason Jul 25 '22 at 14:13
  • 1
    @AndyG Not suitable in this case since it looks like `Array2` is supposed to have dimensions determined at runtime. Regarding the actual fix, I would suggest that instead of trying to write a `memcpy`, write out the actual nested `for` loop that copies each individual value in `ar.array` into the corresponding position in `array` – Nathan Pierson Jul 25 '22 at 14:13
  • 2
    I see both `array=new int*[r];` and `array=new int*[r*c];` -- it seems that you haven't yet decided how many `int*`s `array` should be pointing to. – Drew Dormann Jul 25 '22 at 14:16
  • Additionally, given that you have multiple `int *`s, you can't realistically expect, somehow, a single `memcpy` to take care of that. Which C++ textbook told you to use `memcpy` here? You should throw it away, it's a bad textbook, and get a real C++ textbook that will explain how to use `std::copy` safely. – Sam Varshavchik Jul 25 '22 at 14:18
  • In C++, `memcpy` is used to copy a span of_contiguous_ bytes. Your collection of many pointers and `new` allocations does not produce a block of contiguous bytes. Your program is crashing because `memcpy` does not know or care that `array` is a collection of pointers to data allocated elsewhere. – Drew Dormann Jul 25 '22 at 14:23
  • @AndrewLiu [See this example of a 2D array class](https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048). – PaulMcKenzie Jul 25 '22 at 14:27
  • @ Nathan Pierson ,I have defined 'array' as private, so I have to use the member function 'getArray',but when I run it , the situation seems get worse. ... – Andrew Liu Jul 25 '22 at 14:30
  • @AndrewLiu -- The class you wrote is fundamentally broken. It is missing the user-defined copy constructor, in addition to what others have mentioned. Take the code at the link I posted (the `Array2D` class), compile it, run it, and see how it works. – PaulMcKenzie Jul 25 '22 at 14:33
  • @Drew Dormann I have try to use 1 dimension array to express it ,but failed ,and I forget to change the code to the original state. – Andrew Liu Jul 25 '22 at 14:33
  • 1
    The private member as the backing store representation of the 2D array should be a 1D `std::vector`. Then most of your problems will be eliminated. – Eljay Jul 25 '22 at 14:37
  • 2
    It doesn't matter that `array` is `private`, you're inside an `Array2` member function and have access to its private variables. Coding by trial and error is not going to get you very far. – Nathan Pierson Jul 25 '22 at 14:38
  • 1
    @AndrewLiu -- `int main() { Array2 b; }` -- That one line program invokes undefined behavior when the destructor is called. Why? You didn't initialize `array` in the default constructor (or any of the other member variables). If a one-line program cannot work correctly, don't expect anything more complex than that to work. Your example `main` program totally skips over the easy cases, and doesn't even test copy construction. – PaulMcKenzie Jul 25 '22 at 14:40
  • Speaking of not testing copy construction: Printing `"character constructor"` during `operator=` is very misleading. It's not _any_ kind of constructor, it's an assignment operator. It's also confusing printing it in your two-argument constructor because I'm not sure what makes it a "character" constructor, but at least that is in fact a constructor. – Nathan Pierson Jul 25 '22 at 14:51
  • @PaulMcKenzie "See this example of a 2D array class" This class is very useful.thanks – Andrew Liu Jul 25 '22 at 14:58
  • @AndrewLiu [Here is your main program using the Array2D class](https://godbolt.org/z/WqY6sxeKb). – PaulMcKenzie Jul 25 '22 at 15:04

0 Answers0