对这两个赋值运算符之间的差异感到困惑

时间:2019-05-08 20:00:39

标签: c++

我有以下称为CoordinatesList的类。它包含一个动态的坐标数组,其中每个坐标具有3个整数。 x,y和z。 在类CoordinatesList中,我有两个不同的成员operator =,我对它们之间的区别感到有些困惑?

如果我继承了CoordinatesList类中的类坐标,它将起到相同的作用

class Coordinates {//this is a complete class, do not modify it.
public:
    Coordinates() {
        x = new int; y = new int; z = new int;
        *x = *z = *y = 0;
    }
    Coordinates(int _x, int _y, int _z) {
        x = new int; y = new int; z = new int;
        *x = _x;
        *z = _y;
        *y = _z;
    }
    Coordinates(const Coordinates& rhs) { // copy constructor
        x = new int; y = new int; z = new int;
        *x = *(rhs.x);
        *y = *(rhs.y);
        *z = *(rhs.z);
    }
    ~Coordinates() {
        delete x; delete y; delete z;
    }
    void operator=(const Coordinates& rhs) {//simplified operator=
        *x = *(rhs.x);
        *y = *(rhs.y);
        *z = *(rhs.z);
    }
    int getx() const { return *x; }
    int gety() const { return *y; }
    int getz() const { return *z; }
    void setx(int _x) { *x = _x; }
    void sety(int _y) { *y = _y; }
    void setz(int _z) { *z = _z; }
    friend ostream& operator<< (ostream& out, const Coordinates& rhs) {
    out << "[" << *(rhs.x) << "," << *(rhs.y) << "," << *(rhs.z) << "]" << endl;
    return out;
    }

private:
    int *x, *y, *z;
}; //--------------------------------------------------------------



class CoordinatesList {
public:

    /*CoordinatesList &  operator=(const CoordinatesList &rhs)
    {

        if (size != rhs.size)
        {
            delete[] list;
            size = rhs.size;
            list = new Coordinates[size];
        }
        for (int i = 0; i < size; i++)
        {
            list[i].Coordinates::operator=(rhs.list[i]);
        }
        return *this;

    } */

    CoordinatesList operator=(const CoordinatesList & rhs) 
    {

        //check if sizes are differernt
        if (size != rhs.size) 
        {   
            delete[] list; //this calls ~coordinates 
            size = rhs.size; 
            list = new Coordinates[size]; 
        }
        //copy content      
        for (int i = 0; i < size; i++) {
            //list[i] = rhs.list[i]; 
//will work as operator= is defined for Coordinates
            list[i].setx(rhs.list[i].getx());
            list[i].sety(rhs.list[i].gety());
            list[i].setz(rhs.list[i].getz());
        }
        return *this; 
    }
    private:
    Coordinates * list;
    int size;
};

1 个答案:

答案 0 :(得分:1)

using CL = CoordinatesList;以节省输入内容。

区别在于,一个返回引用,一个返回副本。 惯用的方法是返回对*this的引用,因此请使用此引用: CL& operator=(const CL& rhs){/*...*/ return *this;} 请注意,同时定义两个版本将导致编译器错误,因为函数不能仅因其返回值而有所不同。

operator=的用法:

CL a = CL(<args>);// (1)
CL b,c;
b = a; // (2)
b.operator=(a); //(3)
c = b = a; // (4)
c.operator=(b.operator=(a)); // (5)

(1)调用任何CL::operator=,而是调用构造函数CL::CL(<args>)。正在创建对象,因此无论等号如何都必须调用构造函数。

(2)仅是(3)的语法糖。调用CL::operator=并丢弃所有返回值。

(4)再次是(5)的唯一语法糖。首先,对右边的operator=进行求值,并将返回的值作为参数传递给左边的operator=。在这种情况下,让operator=返回一个副本确实会产生一个副本。这就是为什么选择第二种方法的原因,因为它不会产生额外的不必要的成本。同样,这应该很好地解释了为什么该函数会返回任何内容,如果它返回void则将无法使用此语法。