web-dev-qa-db-ja.com

C ++での代入演算子のオーバーロード

代入演算子のオーバーロードには次のコードを使用しました。

SimpleCircle SimpleCircle::operator=(const SimpleCircle & rhs)
{
     if(this == &rhs)
        return *this;
     itsRadius = rhs.getRadius();
     return *this;
}

私のコピーコンストラクタはこれです:

SimpleCircle::SimpleCircle(const SimpleCircle & rhs)
{
    itsRadius = rhs.getRadius();
}

上記の演算子のオーバーロードコードでは、新しいオブジェクトが作成されるときにコピーコンストラクターが呼び出されます。したがって、私は以下のコードを使用しました:

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    if(this == &rhs)
       return *this;
    itsRadius = rhs.getRadius();
    return *this;
}

その完全な動作とコピーコンストラクタの問題は回避されますが、これに関して(私にとって)未知の問題はありますか?

32
kaushik

代入演算子の2番目のバージョンには問題はありません。実際、それが代入演算子の標準的な方法です。

Edit:実装自体ではなく、代入演算子の戻り型を参照していることに注意してください。コメントで指摘されているように、実装自体は別の問題です。 here を参照してください。

17
juanchopanza

状況下では、ほぼ確実に自己割り当てのチェックをスキップする方が良いでしょう-単純型(おそらくdouble)のように見えるメンバーを1つだけ割り当てている場合、通常は回避するよりもその割り当てを行う方が速いですそれなので、あなたは次のようになります:

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    itsRadius = rhs.getRadius(); // or just `itsRadius = rhs.itsRadius;`
    return *this;
}

多くの古い本や品質の低い本が自己割り当ての確認を勧めていることを理解しています。少なくとも私の経験では、それなしで済ませることは十分にまれです(そして、オペレーターが正確性のためにそれに依存している場合、ほぼ確実に例外安全ではありません)。

余談ですが、円を定義するには、通常、中心と半径が必要であり、コピーまたは割り当てを行うときは、両方をコピー/割り当てたいことに注意してください。

7
Jerry Coffin

2番目はかなり標準です。多くの場合、代入演算子から参照を返すことで、a = b = c;期待どおりに解決します。割り当てからコピーを返したい場合は考えられません。

注意すべきことの1つは、ディープコピーを必要としない場合、コンパイラーによって生成された暗黙のコピーコンストラクターと代入演算子を使用するのが最善であると考える場合があることです。本当にあなた次第です...

編集:

基本的な呼び出しは次のとおりです。

SimpleCircle x; // default constructor
SimpleCircle y(x); // copy constructor
x = y; // assignment operator

割り当て演算子の最初のバージョンがあったとしましょう:

SimpleCircle SimpleCircle::operator=(const SimpleCircle & rhs)
{
     if(this == &rhs)
        return *this; // calls copy constructor SimpleCircle(*this)
     itsRadius = rhs.getRadius(); // copy member
     return *this; // calls copy constructor
}

コピーコンストラクターを呼び出し、thisへの参照を渡して、返されるコピーを作成します。 2番目の例では、thisへの参照を返すだけでコピーを回避しています

SimpleCircle & SimpleCircle::operator=(const SimpleCircle & rhs)
{
    if(this == &rhs)
       return *this; // return reference to this (no copy)
    itsRadius = rhs.getRadius(); // copy member
    return *this; // return reference to this (no copy)
}
7
AJG85

演算子のオーバーロードを使用する正しい方法です。値のコピーを避けて参照することでオブジェクトを取得できます。

0
Andy_aka_mol

これは役に立つかもしれません:

// Operator overloading in C++
//assignment operator overloading
#include<iostream>
using namespace std;

class Employee
{
private:
int idNum;
double salary;
public:
Employee ( ) {
    idNum = 0, salary = 0.0;
}

void setValues (int a, int b);
void operator= (Employee &emp );

};

void Employee::setValues ( int idN , int sal )
{

salary = sal; idNum = idN;

}

void Employee::operator = (Employee &emp)  // Assignment operator overloading function
{
salary = emp.salary;
}

int main ( )
{

Employee emp1;
emp1.setValues(10,33);
Employee emp2;
emp2 = emp1; // emp2 is calling object using assignment operator

}
0
user2808359