转载:http://blog.csdn.net/puppet_master/article/details/46973435
一.简介
operator= 运算符重载,就类似正常我们为变量赋值(如a = b)时的情况,但是我们自己写的类,内部肯定有各种字段,赋值当然不会就像a=b那么简单啦。
如果我们自己写重载操作符=,编译器也会为我们生成一个,但是这个函数功能很弱,只能实现浅赋值。
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- public:
- CopyTest(int i, string n):id(i),name(n)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- void Display()
- {
- cout<<name<<” ”<<id<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”);
- CopyTest test2(2, ”haha”);
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test1.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
public:
CopyTest(int i, string n):id(i),name(n)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
void Display()
{
cout<<name<<" "<<id<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”);
CopyTest test2(2, “haha”);
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test1.Display();
system("pause");
return 0;
}
结果:
Before operator = test2 is: haha 2
After operator = test2 is hehe 1
请按任意键继续…
可见,虽然我们并没有写那个operator=的函数,但是我们仍然实现了对象的赋值。
二.自己DIY一个operator=函数
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- public:
- CopyTest(int i, string n):id(i),name(n)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- CopyTest& operator= (const CopyTest& e)
- {
- name = e.name;
- id = e.id;
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
- void Display()
- {
- cout<<name<<” ”<<id<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”);
- CopyTest test2(2, ”haha”);
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test1.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
public:
CopyTest(int i, string n):id(i),name(n)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
CopyTest& operator= (const CopyTest& e)
{
name = e.name;
id = e.id;
cout<<"operator= function is called!"<<endl;
return *this;
}
void Display()
{
cout<<name<<" "<<id<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”);
CopyTest test2(2, “haha”);
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test1.Display();
system("pause");
return 0;
}
operator= function is called!
After operator = test2 is hehe 1
请按任意键继续…
三.operator=返回一个本对象的引用
- a = b = c;
- //相当于:
- a = (b = c);
a = b = c;
//相当于:
a = (b = c);
即所谓的连锁赋值,赋值操作符必须返回一个reference指向操作符的左侧实参。
- CopyTest& operator= (const CopyTest& e)
- { …
- return *this;
- }
CopyTest& operator= (const CopyTest& e)
{ ...
return *this;
}
- </pre><pre name=“code” class=“cpp”>//在+=,-=,*=,/=等情况也都成立
</pre><pre name="code" class="cpp">//在+=,-=,*=,/=等情况也都成立
当然,这不是强制的,只是一个协议。不遵守程序并无问题,但是这条协议被所有内置数据类型,string,vector等等C++几乎最常用的类型所遵守,我们还是随大流吧…
四.深拷贝浅拷贝
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- int* pointer;
- public:
- CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- CopyTest& operator= (const CopyTest& e)
- {
- name = e.name;
- id = e.id;
- delete pointer;
- pointer = new int(*e.pointer);
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
- void Display()
- {
- cout<<”name: ”<<name<<“ ”<<“id: ”<<id<<“ pointer: ”<<*pointer<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”, new int(1));
- CopyTest test2(2, ”haha”, new int (2));
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test1.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
int* pointer;
public:
CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
CopyTest& operator= (const CopyTest& e)
{
name = e.name;
id = e.id;
delete pointer;
pointer = new int(*e.pointer);
cout<<"operator= function is called!"<<endl;
return *this;
}
void Display()
{
cout<<"name: "<<name<<" "<<"id: "<<id<<" pointer: "<<*pointer<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”, new int(1));
CopyTest test2(2, “haha”, new int (2));
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test1.Display();
system("pause");
return 0;
}
operator= function is called!
After operator = test2 is name: hehe id: 1 pointer: 1
请按任意键继续…
五.防止对象自我赋值
- test2 = test2;
test2 = test2;
那么结果:
Before operator = test2 is: name: haha id: 2 pointer: 2
operator= function is called!
After operator = test2 is name: haha id: 2 pointer: -17891602
请按任意键继续…
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- int* pointer;
- public:
- CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- CopyTest& operator= (const CopyTest& e)
- {
- if (this == &e)
- return *this;
- name = e.name;
- id = e.id;
- delete pointer;
- pointer = new int(*e.pointer);
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
- void Display()
- {
- cout<<”name: ”<<name<<“ ”<<“id: ”<<id<<“ pointer: ”<<*pointer<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”, new int(1));
- CopyTest test2(2, ”haha”, new int (2));
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test2;
- cout<<”After operator = test2 is ”;
- test2.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
int* pointer;
public:
CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
CopyTest& operator= (const CopyTest& e)
{
if (this == &e)
return *this;
name = e.name;
id = e.id;
delete pointer;
pointer = new int(*e.pointer);
cout<<"operator= function is called!"<<endl;
return *this;
}
void Display()
{
cout<<"name: "<<name<<" "<<"id: "<<id<<" pointer: "<<*pointer<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”, new int(1));
CopyTest test2(2, “haha”, new int (2));
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test2;
cout<<"After operator = test2 is ";
test2.Display();
system("pause");
return 0;
}
结果:
After operator = test2 is name: haha id: 2 pointer: 2
请按任意键继续…
六.防止拷贝过程中内存申请失败导致原来内容被破坏
- CopyTest& operator= (const CopyTest& e)
- {
- if (this == &e)
- return *this;
- name = e.name;
- id = e.id;
- //先用一个临时指针变量存储
- int* tempPointer = new int (*e.pointer);
- //如果上一步执行成功,才删除原有内容
- delete pointer;
- //赋值
- pointer = tempPointer;
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
CopyTest& operator= (const CopyTest& e)
{
if (this == &e)
return *this;
name = e.name;
id = e.id;
//先用一个临时指针变量存储
int* tempPointer = new int (*e.pointer);
//如果上一步执行成功,才删除原有内容
delete pointer;
//赋值
pointer = tempPointer;
cout<<"operator= function is called!"<<endl;
return *this;
}
结果:
operator= function is called!
After operator = test2 is name: hehe id: 1 pointer: 1
请按任意键继续…
七.去除operator= 和拷贝构造函数中的冗余代码
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- int* pointer;
- public:
- CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- //拷贝构造函数
- CopyTest(const CopyTest& e)
- {
- name = e.name;
- id = e.id;
- pointer = new int ();
- *pointer = *e.pointer;
- cout<<”Copy Construct is called!”<<endl;
- }
- CopyTest& operator= (const CopyTest& e)
- {
- CopyTest temp(e);
- std::swap(*this, temp);
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
- void Display()
- {
- cout<<”name: ”<<name<<“ ”<<“id: ”<<id<<“ pointer: ”<<*pointer<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”, new int(1));
- CopyTest test2(2, ”haha”, new int (2));
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test2.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
int* pointer;
public:
CopyTest(int i, string n, int* p):id(i),name(n), pointer(p)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
//拷贝构造函数
CopyTest(const CopyTest& e)
{
name = e.name;
id = e.id;
pointer = new int ();
*pointer = *e.pointer;
cout<<"Copy Construct is called!"<<endl;
}
CopyTest& operator= (const CopyTest& e)
{
CopyTest temp(e);
std::swap(*this, temp);
cout<<"operator= function is called!"<<endl;
return *this;
}
void Display()
{
cout<<"name: "<<name<<" "<<"id: "<<id<<" pointer: "<<*pointer<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”, new int(1));
CopyTest test2(2, “haha”, new int (2));
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test2.Display();
system("pause");
return 0;
}
不过,这里我的程序会不停的调用swap函数,直到stack overflow…查了半天也没差出来,以后来填坑。
- CopyTest& operator= (CopyTest& e)
- {
- std::swap(*this, e);
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
CopyTest& operator= (CopyTest& e)
{
std::swap(*this, e);
cout<<"operator= function is called!"<<endl;
return *this;
}
直接使用函数的实参,来作为swap的参数,但是注意要把const去掉。
简单总结一下:
八.复制对象时勿忘其每一个成分(拷贝构造函数和operator=都要注意)
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- public:
- CopyTest(int i, string n):id(i),name(n)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- //拷贝构造函数
- CopyTest(const CopyTest& e)
- {
- name = e.name;
- id = e.id;
- cout<<”Copy Construct is called!”<<endl;
- }
- CopyTest& operator= (CopyTest& e)
- {
- if (this == &e)
- return *this;
- name = e.name;
- //id = e.id;如果我们忘记写这一句,编译器并不会报错
- cout<<”operator= function is called!”<<endl;
- return *this;
- }
- void Display()
- {
- cout<<”name: ”<<name<<“ ”<<“id: ”<<id<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTest test1(1, ”hehe”);
- CopyTest test2(2, ”haha”);
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test2.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
public:
CopyTest(int i, string n):id(i),name(n)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
//拷贝构造函数
CopyTest(const CopyTest& e)
{
name = e.name;
id = e.id;
cout<<"Copy Construct is called!"<<endl;
}
CopyTest& operator= (CopyTest& e)
{
if (this == &e)
return *this;
name = e.name;
//id = e.id;如果我们忘记写这一句,编译器并不会报错
cout<<"operator= function is called!"<<endl;
return *this;
}
void Display()
{
cout<<"name: "<<name<<" "<<"id: "<<id<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTest test1(1, “hehe”);
CopyTest test2(2, “haha”);
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test2.Display();
system("pause");
return 0;
}
结果:
Before operator = test2 is: name: haha id: 2
operator= function is called!
After operator = test2 is name: hehe id: 2
请按任意键继续…
九.派生类中的拷贝要考虑基类部分的拷贝(拷贝构造函数和operator=都要注意)
- // C++Test.cpp : 定义控制台应用程序的入口点。
- //
- #include “stdafx.h”
- #include <iostream>
- #include <string>
- using namespace std;
- class CopyTest
- {
- private:
- string name;
- int id;
- public:
- CopyTest(int i, string n):id(i),name(n)
- {
- //cout<<”Construct!”<<endl;
- }
- ~CopyTest()
- {
- //cout<<”No”<<id<<” ”<<”Destruct!”<<endl;
- }
- //拷贝构造函数
- CopyTest(const CopyTest& e)
- {
- name = e.name;
- id = e.id;
- cout<<”CopyTest CopyConstructor is called!”<<endl;
- }
- CopyTest& operator= (const CopyTest& e)
- {
- if (this == &e)
- return *this;
- name = e.name;
- id = e.id;
- cout<<”CopyTest operator= function is called!”<<endl;
- return *this;
- }
- virtual void Display()
- {
- cout<<”name: ”<<name<<“ ”<<“id: ”<<id<<endl;
- }
- };
- class CopyTestChild : public CopyTest
- {
- private:
- int childId;
- public:
- CopyTestChild(int i, string n, int ci): CopyTest(i, n), childId(ci)
- {
- //cout<<”CopyTestCilid is Constructed!”<<endl;
- }
- ~CopyTestChild()
- {
- }
- //子类拷贝构造函数调用基类拷贝构造函数
- CopyTestChild(const CopyTestChild& e) : CopyTest(e)
- {
- childId = e.childId;
- cout<<”CopyTestChild CopyConstructor is called!”<<endl;
- }
- CopyTestChild& operator= (const CopyTestChild& e)
- {
- if (this == &e)
- return *this;
- //调用基类operator=函数
- CopyTest::operator=(e);
- childId = e.childId;
- cout<<”CopyTestChild operator= function is called!”<<endl;
- return *this;
- }
- virtual void Display()
- {
- CopyTest::Display();
- cout<<”ChildId is ”<<childId<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTestChild test1(1, ”hehe”, 1);
- CopyTestChild test2(2, ”haha”, 2);
- cout<<”Before operator = test2 is: ”;
- test2.Display();
- test2 = test1;
- cout<<”After operator = test2 is ”;
- test2.Display();
- system(”pause”);
- return 0;
- }
// C++Test.cpp : 定义控制台应用程序的入口点。
//
include "stdafx.h"
include <iostream>
include <string>
using namespace std;
class CopyTest
{
private:
string name;
int id;
public:
CopyTest(int i, string n):id(i),name(n)
{
//cout<<"Construct!"<<endl;
}
~CopyTest()
{
//cout<<"No"<<id<<" "<<"Destruct!"<<endl;
}
//拷贝构造函数
CopyTest(const CopyTest& e)
{
name = e.name;
id = e.id;
cout<<"CopyTest CopyConstructor is called!"<<endl;
}
CopyTest& operator= (const CopyTest& e)
{
if (this == &e)
return *this;
name = e.name;
id = e.id;
cout<<"CopyTest operator= function is called!"<<endl;
return *this;
}
virtual void Display()
{
cout<<"name: "<<name<<" "<<"id: "<<id<<endl;
}
};
class CopyTestChild : public CopyTest
{
private:
int childId;
public:
CopyTestChild(int i, string n, int ci): CopyTest(i, n), childId(ci)
{
//cout<<”CopyTestCilid is Constructed!”<<endl;
}
~CopyTestChild()
{
}
//子类拷贝构造函数调用基类拷贝构造函数
CopyTestChild(const CopyTestChild& e) : CopyTest(e)
{
childId = e.childId;
cout<<"CopyTestChild CopyConstructor is called!"<<endl;
}
CopyTestChild& operator= (const CopyTestChild& e)
{
if (this == &e)
return *this;
//调用基类operator=函数
CopyTest::operator=(e);
childId = e.childId;
cout<<"CopyTestChild operator= function is called!"<<endl;
return *this;
}
virtual void Display()
{
CopyTest::Display();
cout<<"ChildId is "<<childId<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CopyTestChild test1(1, “hehe”, 1);
CopyTestChild test2(2, “haha”, 2);
cout<<"Before operator = test2 is: ";
test2.Display();
test2 = test1;
cout<<"After operator = test2 is ";
test2.Display();
system("pause");
return 0;
}
结果:
Before operator = test2 is: name: haha id: 2
ChildId is 2
CopyTest operator= function is called!
CopyTestChild operator= function is called!
After operator = test2 is name: hehe id: 1
ChildId is 1
请按任意键继续…
- int _tmain(int argc, _TCHAR* argv[])
- {
- CopyTestChild test1(1, ”hehe”, 1);
- CopyTestChild test2(test1);
- test2.Display();
- system(”pause”);
- return 0;
- }
int _tmain(int argc, _TCHAR* argv[])
{
CopyTestChild test1(1, "hehe", 1);
CopyTestChild test2(test1);
test2.Display();
system("pause");
return 0;
}
CopyTestChild CopyConstructor is called!
name: hehe id: 1
ChildId is 1
请按任意键继续…
十.关于拷贝构造函数和operator=函数中相同的部分怎么处理
</div>
</div>