如何使用'='将类的对象复制到同一个类的另一个对象

时间:2012-03-02 05:36:48

标签: c++ copy overloading

如何使用'='将类的对象复制到同一个类的另一个对象。我知道我们必须超载操作员。这是我到目前为止所拥有的

#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 个答案:

答案 0 :(得分:2)

正确的解决方案是这样的:

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

答案 1 :(得分:0)

在赋值运算符中不需要临时数组对象,您应该在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;
}

答案 2 :(得分:0)

你在运算符重载中实现的内容非常混乱,对我来说似乎不对

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,然后你没有使用 它在任何地方!!

  2. 你不需要在函数内部创建一个新对象,因为“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;
    }
    

答案 3 :(得分:0)

您的复制构造函数也看起来不对,它不会复制数组的内容。

我同意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的名称让我担心你以后会添加第二个数组。不要这样做,编写一个正确管理两个资源的类比编写一个正确管理一个资源的类和另一个具有两个资源作为数据成员的类要麻烦得多。