Как скопировать объект класса в другой объект того же класса, используя '=' - PullRequest
1 голос
/ 02 марта 2012

Как скопировать объект класса в другой объект того же класса, просто используя '='. Я знаю, что мы должны перегрузить оператора. вот что у меня так далеко

#include<iostream>
#include<conio.h>
#include<iomanip>

using namespace std;



class arr
{
public:
    int *arr1;
    int len;

    arr& operator = (const arr& eq) //for copying two arrays. <--- my overloader
    {
        arr temp1(eq.len);
        arr *pttemp;
        int i=0;
        //temp.arr1=new int[eq.len];
        //temp.len = eq.len;
        for(i = 0 ; i < eq.len ; i++)
        {
            temp1.arr1[i] = eq.arr1[i];
        }       
        pttemp = &temp1;
        return temp1;
    };

    friend istream& operator >> (istream& ist, arr & r)
    {
        static int i = 0;
        int *arrNew;

        if (i == r.len)
        {
            r.len *=2;
            arrNew = new int[r.len]; // allocate the new array              
            for(int j = 0; j < r.len/2; j++)// copy the old array to the first half of the new array
            arrNew[j] = r.arr1[j];// delete the old array         
            delete [] r.arr1;// let arr point to the new array and continue use arr     
            r.arr1 = arrNew;
            delete arrNew;
        }

        ist>>r.arr1[i];
        i++;

        return ist;
    }

    arr() //initializing constructor
    {
        len = 5;
        arr1 = new int[len];
    };

    arr(int size) //initializing constructor with args
    {
        len = size;
        arr1 = new int[len];
    };

    arr(arr& a) : arr1(a.arr1) //copy constructor
    {
        arr1 = new int[len];
    };

    ~arr() //delete constructor
    {
        delete arr1;
    };



};




void main()
{
    int size = 5,i,temp,trig = 0;
    arr orig(size), asc(size), desc(size);  

    //generate random numbers for orig

    for (i = 0 ; i < size ; i++)
    {
        orig.arr1[i] = rand();
    }

    //copy original set to asc and desc
    asc = orig;
    desc = orig;

    //sorting ascending
    for (i = 0 ; i < size-1 ; i++)
    {
        trig = 1;
        if (asc.arr1[i] < asc.arr1[i+1])
        {
            temp = asc.arr1[i];
            asc.arr1[i] = asc.arr1[i+1];
            asc.arr1[i+1] = temp;
            trig = 0;
        }
        if (trig = 1)
            break;
        if (i == size - 1)
        {
            i = 0;
        }
    }

    //sorting descending
    for (i = 0 ; i < size-1 ; i++)
    {
        trig = 1;
        if (desc.arr1[i] > desc.arr1[i+1])
        {
            temp = desc.arr1[i];
            desc.arr1[i] = desc.arr1[i+1];
            desc.arr1[i+1] = temp;
            trig = 0;
        }
        if (trig = 1)
            break;
        if (i == size - 1)
        {
            i = 0;
        }
    }

    //printing  
    cout<<"Original Array: ";
    for (i = 0 ; i < size ; i++)
    {
        cout<<orig.arr1[i]<<" ";
    }
    cout<<endl;
    cout<<"Ascending Array: ";
    for (i = 0 ; i < size ; i++)
    {
        cout<<asc.arr1[i]<<" ";
    }
    cout<<endl;

    cout<<"Descending Array: ";
    for (i = 0 ; i < size ; i++)
    {
        cout<<desc.arr1[i]<<" ";
    }
    cout<<endl;

    getch();

}

Он компилируется правильно, но в нем («asc» и «desc») отображаются числа, отличные от объекта «orig».

Ответы [ 4 ]

2 голосов
/ 02 марта 2012

Правильное решение выглядит примерно так:

struct Foo
{
    std::vector<int> arr;
    friend std::ifstream & operator>>(/*...*/);
};

Неявно определенный оператор присваивания уже делает именно то, что вам нужно, а умное повторное использование кода - это сердце программирования на C ++ («язык для проектирования библиотеки»).

Если вы хотите написать это от руки, вы должны сделать копию самостоятельно:

struct Bar
{
    unsigned int len;
    int * arr;

    Bar & operator=(Bar const & rhs)
    {
        len = rhs.len; 
        delete[] arr;
        arr = new int[len];
        for (unsigned int i = 0; i != len; ++i) { arr[i] = rhs.arr[i]; }
        return *this;
    }

    Bar() : len(), arr() { }
    // more constructors

    Bar(Bar const &);  // exercise: write this!

    ~Bar() { delete[] arr; }
};

Это ужасная, ужасная идея, поскольку этот шаблон невообще обобщать: это не исключение - представьте, что одна из копий в for -петле вызвала исключение.Теперь вы потеряли исходные данные и утечка памяти.

Лучшим решением было бы сначала выделить временный буфер:

int * temp = new int[len];
for (...) temp[i] = rhs.arr[i];

delete[] arr;
arr = temp;

Теперь этот код быстростановится очень уродливым, и представьте, что у вас их было больше одного!

В двух словах: используйте std::vector.

0 голосов
/ 02 марта 2012

Ваш конструктор копирования также выглядит неправильно, он не копирует содержимое массива.

Я согласен с Kerrek, что вы должны использовать vector.Но поскольку вы, похоже, пытаетесь заново реализовать vector для себя, вот простой «правильный» способ управления ресурсами в вашем классе, например:

class arr
{
  public:
    // switch order of data members, we want to initialize "len" first
    int len;
    int *arr1;

    // default constructor
    // you could use "new int[len]()" instead, to zero-initialize the array
    arr() : len(5), arr1(new int[len]) {}

    // constructor with size
    arr(int size) : len(size), arr1(new int[len]) {}

    // copy constructor
    arr(const arr &rhs) : len(rhs.len), arr1(new int[len]) {
        std::copy(rhs.arr1, rhs.arr1 + len, arr1);
    }

    // destructor
    ~arr() {
        delete[] arr1; // *not* "delete", you *must* use "delete[]"
    }

    // swap function (this is useful, observe that it cannot throw)
    void swap(arr &rhs) {
        std::swap(len, rhs.len);
        std::swap(arr1, rhs.arr1);
    }

    // assignment operator
    arr &operator=(arr temp) { // parameter by value uses the copy ctor
        // so, anything that could throw (the allocation) is complete,
        // before we make any modifications to this object.
        // see how useful "swap" is, and the fact it cannot throw?
        swap(temp);
        return *this;
    }

    // for C++11
    // move constructor
    arr(arr &&rhs) : len(rhs.len), arr1(rhs.arr1) {
        rhs.arr1 = 0;
    }
};

Кстати, названиечлен данных arr1 заставляет меня опасаться, что вы добавите второй массив позже.Не делайте этого, гораздо сложнее написать класс, который правильно управляет двумя ресурсами, чем написать класс, который правильно управляет одним ресурсом, и другой класс, в котором два из них являются членами данных.

0 голосов
/ 02 марта 2012

то, что вы реализовали в перегрузке операторов, довольно запутанно и мне кажется неправильным

arr& operator = (const arr& eq) //for copying two arrays. <--- my overloader
    {
        arr temp1(eq.len);
        arr *pttemp;
        int i=0;
        //temp.arr1=new int[eq.len];
        //temp.len = eq.len;
        for(i = 0 ; i < eq.len ; i++)
        {
            temp1.arr1[i] = eq.arr1[i];
        }       
        pttemp = &temp1;
        return temp1;
    };
  1. 1. Почему вы создаете новую температуру объекта?

    2. зачем создавать указатель типа arr.и присваивая pttemp указатель на temp, область действия которого находится в функции, и тогда вы ее нигде не используете !!

вам не нужно создавать новый объект внутри функции как "this"указатель неявно передается в функцию.

вы должны перегрузить его таким образом

arr& operator = (const arr& source)
{
 //this->len = source.len;
 len =  source.len;

for(int i=0;i < source.len ; i++)
{
//this->arr1[i] = source.arr1[i];
arr1[i] = source.arr1[i];
}

return *this;
}
0 голосов
/ 02 марта 2012

Вам не нужен объект временного массива в операторе присваивания, и вы должны скопировать в массив в this, а затем вернуть *this:

arr &operator=(const arr &eq)
{
    // If "this" already has an array, then delete it
    if (arr1)
        delete [] arr1;

    // Create a new array of the same length as the one we're assigning from
    len = eq.len;
    arr1 = new int [len];

    // And copy the array
    memcpy(arr1, eq.arr1, len * sizeof(int));

    // Returning "*this" allows the assignment operator to be chained
    return *this;
}
...