C++代入演算子リロード関数(operator=)
13296 ワード
c++のリロード記号がよく理解されていないため、ここではいくつかの資料を参照して比較的詳細な解釈を提供し、読者や自分で調べるのに便利である.
ここではより詳細な説明がありますが、a=b=cの実行順序に関する説明は正しくありません.
例1
結果1
実行が表示されます.
場合、付与演算子リロード関数が呼び出され、str 2が関数呼び出し者であり、str 1が関数呼び出しのパラメータ(str 2.xxx(str 1)に類似)であることは、通常の関数呼び出しと同様に理解できる. 付与演算子リロード関数パラメータは参照であり、一次オブジェクトのコピー構造を回避します. 同様に、レプリケーション演算子リロード関数関数の戻り値は参照であり、一度のオブジェクトのコピー構造も回避されます.戻り値タイプがMyStrの場合、関数が戻るとlinshi変数が作成され、このポインタが指すオブジェクトが一時変数にコピーされます. もちろん、オブジェクトを返さずに、戻り値をvoidに設定することもできます.しかし、オブジェクトまたは参照を返すときに、a=b=cと同様に、a=(b=c)に等しい連続的な付与を実現することができる.
例2(戻りタイプをMyStrに変更)
結果2
実行
を選択すると、関数はオブジェクトを返し、コピーコンストラクション関数を呼び出して一時変数を生成します.
例3(a=b=c実行順序の検証)
結果3
は,まず構造が3つのオブジェクトであり,nameはそれぞれstr 1,str 2,str 3であることがわかる.そして実行
場合、str 2=str 1を実行し、オブジェクトstr 2がstr 1のnameを取得した後、str 3はstr 2が新しく取得したnameを取得する.
ここではより詳細な説明がありますが、a=b=cの実行順序に関する説明は正しくありません.
例1
#include
#include
using namespace std;
class MyStr
{
private:
char *name = NULL;
int id;
public:
MyStr() {cout << "default
" << endl;}
MyStr(int _id, char *_name) //constructor
{
cout << "constructor" << endl;
id = _id;
name = new char[strlen(_name) + 1];
memcpy(name, _name, strlen(_name) + 1);
}
MyStr(const MyStr& str)
{
cout << "copy constructor" << endl;
id = str.id;
if (name != NULL)
delete name;
name = new char[strlen(str.name) + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
MyStr& operator =(const MyStr& str)//
{
cout << "operator =" << endl;
if (this != &str)
{
if (name != NULL)
delete name;
this->id = str.id;
int len = strlen(str.name);
name = new char[len + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
return *this;
}
~MyStr()
{
delete name;
}
};
int main()
{
MyStr str1(1, "hhxx");
cout << "====================" << endl;
MyStr str2;
str2 = str1;
cout << "====================" << endl;
MyStr str3 = str2;
return 0;
}
結果1
constructor
====================
default
operator =
====================
copy constructor
実行が表示されます.
str2 = str1
場合、付与演算子リロード関数が呼び出され、str 2が関数呼び出し者であり、str 1が関数呼び出しのパラメータ(str 2.xxx(str 1)に類似)であることは、通常の関数呼び出しと同様に理解できる. 付与演算子リロード関数パラメータは参照であり、一次オブジェクトのコピー構造を回避します. 同様に、レプリケーション演算子リロード関数関数の戻り値は参照であり、一度のオブジェクトのコピー構造も回避されます.戻り値タイプがMyStrの場合、関数が戻るとlinshi変数が作成され、このポインタが指すオブジェクトが一時変数にコピーされます. もちろん、オブジェクトを返さずに、戻り値をvoidに設定することもできます.しかし、オブジェクトまたは参照を返すときに、a=b=cと同様に、a=(b=c)に等しい連続的な付与を実現することができる.
例2(戻りタイプをMyStrに変更)
#include
#include
using namespace std;
class MyStr
{
private:
char *name = NULL;
int id;
public:
MyStr() {cout << "default
" << endl;}
MyStr(int _id, char *_name) //constructor
{
cout << "constructor" << endl;
id = _id;
name = new char[strlen(_name) + 1];
memcpy(name, _name, strlen(_name) + 1);
}
MyStr(const MyStr& str)
{
cout << "copy constructor" << endl;
id = str.id;
if (name != NULL)
delete name;
name = new char[strlen(str.name) + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
MyStr operator =(const MyStr& str)//
{
cout << "operator =" << endl;
if (this != &str)
{
if (name != NULL)
delete name;
this->id = str.id;
int len = strlen(str.name);
name = new char[len + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
return *this;
}
~MyStr()
{
delete name;
}
};
int main()
{
MyStr str1(1, "hhxx");
cout << "====================" << endl;
MyStr str2;
str2 = str1;
cout << "====================" << endl;
MyStr str3 = str2;
return 0;
}
結果2
constructor
====================
default
operator =
copy constructor
====================
copy constructor
実行
str2 = str1
を選択すると、関数はオブジェクトを返し、コピーコンストラクション関数を呼び出して一時変数を生成します.
例3(a=b=c実行順序の検証)
#include
#include
using namespace std;
class MyStr
{
private:
char *name = NULL;
int id;
public:
MyStr() {cout << "default
" << endl;}
MyStr(int _id, char *_name) //constructor
{
cout << "constructor" << endl;
id = _id;
name = new char[strlen(_name) + 1];
memcpy(name, _name, strlen(_name) + 1);
}
MyStr(const MyStr& str)
{
cout << "copy constructor" << endl;
id = str.id;
if (name != NULL)
delete name;
name = new char[strlen(str.name) + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
MyStr& operator =(const MyStr& str)//
{
if(name != NULL)
cout << name << " = " << str.name << endl;
cout << "operator =" << endl;
if (this != &str)
{
if (name != NULL)
delete name;
this->id = str.id;
int len = strlen(str.name);
name = new char[len + 1];
memcpy(name, str.name, strlen(str.name) + 1);
}
return *this;
}
~MyStr()
{
delete name;
}
};
int main()
{
MyStr str1(1, "str1");
cout << "====================" << endl;
MyStr str2(2, "str2"), str3(3, "str3");
str3 = str2 = str1;
cout << "====================" << endl;
MyStr str4 = str2;
return 0;
}
結果3
constructor
====================
constructor
constructor
str2 = str1
operator =
str3 = str1
operator =
====================
copy constructor
は,まず構造が3つのオブジェクトであり,nameはそれぞれstr 1,str 2,str 3であることがわかる.そして実行
str3 = str2 = str1
場合、str 2=str 1を実行し、オブジェクトstr 2がstr 1のnameを取得した後、str 3はstr 2が新しく取得したnameを取得する.