1、赋值运算符重载 虽然一个对象可以由一个单一的赋值语句赋值给另一个对象,我们 之前提到的,此操作可能只创建一个逻辑复制(即,由一个成员 复印件)。 在一个逻辑复制,在一个对象的成员将该成员的值在其他 对象。如果一个类有一个指针成员,由成员复印件使 指针成员在两个对象指向同一个对象。 有两个问题与此成员对成员的复制:第一,因为指针在两个 对象共享相同的变量,这个变量的变化而变化的对象。在其他 的话,这两个对象都不是独立的。 第二,如果共享变量在堆上,我们不知道谁是负责 释放内存。这记忆是不自由的,也将是免费的两倍,这是不 允许。 当一个类成员是一个指向堆内存,我们通常需要
2、过载
赋值操作符来创建一个物理副本。
实例1:
//说明动态内存分配的默认分配的危险。
#include
3、 strcpy(title,mr); strcpy(owner, name); balance = y; } void changetitle(char* newname) { if( strlen(newname) > strlen(title) ) { char* tmp = title; title = new char[strlen(newname)+1]; strcpy (title,newname); delete []tmp; } else { strcpy (title,newname); } } void changename(char*
4、newname)
{strcpy (owner,newname);}
~Account () {delete [ ] title;}
private:
char * title;
char owner[MAX_CHAR];
float balance;
};
ostream& operator<< (ostream& os, Account &b)
{
os <<"who:"<< b.title << " " << b.owner
<<" how much="< 5、){
Account acc("Lou","Mr", 100);
Account acc1;
cout << acc;
cout << acc1;
acc1=acc;
cout << acc1;
acc1.changename("jean");
cout << acc1;
cout< 6、uch = 100
who: Mr Jean how much = 100
who: Mr Lou how much = 100
who: Dr. Jean how much = 100
who: Dr. Lou how much = 100
Then: Run time error: trying to delete same memory twice. If
we delete our destructor, then memory leak. The dynamic
memory is not deleted//运行时错误:试图删除该内存的两倍。如果
我们删除我们的析构函 7、数,然后内存泄漏。动态记忆是不会被删除.
解决方案:重载赋值运算符来得到一个完全不同的
复制包括其自己的堆内存:
(深拷贝)。
在一个类的赋值操作符重载,我们通常需要做的四件事:
首先,我们要检查一个对象是否是分配给本身。(这是可能的因为
变量可以通过不同的名字来访问)。如果是分配给本身,我们不
要做什么。
如果它不是一个自的任务,我们必须释放堆内存的指针成员
对象的当前点。
然后,我们复制的右边的左边。
最后,我们返回*this便于分配链接。返回类型是一个常数
参考因为我们要返回原对象(参考),我们不希望它
被用作左值(常数)。如果返回值是不固定的,我们可以
这样 8、的表达式(X = Y)= Z,这实际上意味着,我们分配的Z值的
返回值(X = Y)。换句话说,我们指定Y = X,然后将Z X再次,
这没有意义。
赋值操作符重载函数必须是成员函数。
这4个运算符是真实的:=,(),[ ],->
实例2:
//这个例子定义了类的向量的第二版,具有过载
运算符=,/ / [ ]和<<。
#include 9、
} // a destructor
int get_size( ) const {return size;} // an accessor
const Vector& operator=(const Vector& x);
int& operator[ ](int index) {return rep[index];}
llconst int& operator[ ](int index) const {return rep[index];}
private:
int *rep;
int size;
};
// A constructor initializing the 10、members of rep by the
parameter an_array
Vector:: Vector(int s, int an_array[ ]):size(s), rep(new
int[s])
{
for (int i = 0; i < size; ++i)
{
rep[i] = an_array[i];
}
}
// Note that the initializer uses new int[s] to initialize
rep, but not new int[size]
// because the initializers may not 11、 be evaluated in the
specified order.
const Vector& Vector::operator=(const Vector& x)
{
if( this != &x)
{
size = x.size;
delete [ ] rep; // clean up the old one.
rep = new int[size];
for (int i = 0; i < size; ++i)
{
rep[i] = x.rep[i];
}
}
/*size = x.size;
if (rep != x.rep)
{
delete 12、 [ ] rep; // clean up the old one.
rep = new int[size];
for (int i = 0; i < size; ++i)
{
rep[i] = x.rep[i];
}
}*/
return *this;
}
ostream& operator<<(ostream& out, const Vector& x)
{
int s = x.get_size( );
for (int i = 0; i < s; ++i)
{
out << x[i]< 13、量是通过一个动态数组表示。赋值操作符,
复制构造函数和析构函数是必要的。在类向量以前的版本,我们
不需要这些功能,因为一个物理副本将由编译器创建的如果
分配或复制发生。
操作员+ =。+,* =,和/ =也以同样的方式超载。我们也可以使用这些
运算符过载算子。例如,我们可以实现运算符+ =在
复合类如下:
const Complex& Complex::operator+= (const Complex& c)
{
r += c._r;
i += c._i;
return *this;
}
Then, the operator + can be overloaded 14、as the following:
const Complex operaotr+ (const Complex& c1, const Complex&
c2)
{
Complex temp(c1);
temp += c2;
return temp;
}
Or, implement it as a member function:
const Complex Complex::operator+(const Complex& c) const
{
Complex temp(*this);
temp += c;
return temp;
}
ll
ll
ll






