C++中几个特殊运算符的重载(= 、++、--、下标运算符的重载)

一、赋值运算符的重载

       对于任何一个类,如果用户没有定义赋值运算符函数,那么系统会为其生成一个默认的赋值运算符函数,在对应的数据成员之间赋值,一般情况下默认的赋值元素运算符函数还能满足用户需求,但是,当类中含有指针型的数据成员时候,会出现如下问题:比如 arry1 = arry2;

(1)会引起原来对象内存的泄漏,就会引起arry1的内存泄漏;在定义arry1时,构造函数根据给出的数组的上下界为arry1动态申请一块空间,在空间的首地址存储在数据成员storage中,当执行arry1 = arry2时,默认的赋值运算符函数,只是将arry1的指针也指向了arry2内存空间;那么原来的内存空间本来是由storage指向的,现在storage指向了arry2,那么它被丢了,造成内存泄漏;

(2)俩个对象的操作会相互影响;因为arry1 和 arry2的空间都是arry2的空间;

(3)当俩个对象析构时,后面析构的那个对象会出错,因为它指向的那块内存已经被前一个对象析构掉了;

#include<iostream>
#include<vld.h>
#include<string.h>
using namespace std;
class Array
{
public:
	Array(int n)
	{
		cout<<"Array()"<<endl;
		str = new char[n];
		for(int i =0;i< n;++n)
		{
			str[i] = 0;
		}
	}
	Array& operator=(const Array& a)
	{
		cout<<"operator"<<endl;
		if(this == &a)return *this;
		delete []str;
		int length = strlen(a.str);
		str = new char[length];
		return *this;
	}
	~Array()
	{
		delete []str;
	}
private:
	char * str;
};
int main()
{
	Array arry1(3);
	Array arry2(4);
	arry1 = arry2;
	return 0;
}
问题1:为什么已经将参数的值赋值给了当前对象,还需要返回*this值呢?

 答:在C++中,赋值是一种运算,它可以构成一个表达式,而且表达式的值是左边对象的值,所以赋值运算符函数必须返回赋给左边对象的值;它方便在一次给另外一个对象赋值:arry3 = arry1 = arry2;
二、下标运算符的重载[]

    下标运算符是一个二元运算符,第一个运算数是当前对象,第二个运算数是下标;C++规定下标运算符的重载必须重载成成员函数;定义式:数组元素类型 &operator[] (int  index);

 三、++和--的重载

     ++ 和--都是一元运算符,他们都可以被重载成成员函数或者友元函数,因为这俩个对象改变运算对象的状态,更倾向于作为成员函数;

   ++和--有俩种用法:作为前缀使用了,返回的是修改以后对象的值;作为后缀使用时,返回的是修改以前对象的值;为此,对于++和--运算,每个运算符都必须提供俩个重载函数,一个处理前缀,一个处理后缀;但是,前缀函数和后缀函数的参数的个数和参数的类型完全一样,所以普通的函数重载无法区分这里个函数;

  C++规定后缀运算重载函数接受一个额外(无用的)int形式参数,这样就把前缀和后缀区分开了;

定义如下:假设有一个计数器类Counter;

  Counter & Counter::operator++();

  Counter Counter::operator++(int x);

为什么前缀返回的是counter的引用?后缀返回的是非引用呢?

因为前缀++返回的是当前对象的引用(也就是刚刚自增后的对象),因为当前对象*this是作为Counter&返回的,这样可以使得前缀自增的对象可以作为左值来使用(可以给变量赋值);

后缀的++,为了返回自增前的对象,我们定义了一个零时对象,零时对象在函数结束之后就消失了了,声明成非引用,在临时对象消失之前它会将自己给系统的零时变量,这样这个零时变量的值就不会无效,但是,如果声明成引用,在函数结束后,他就消失了,那么返回的引用将是一个无效空间;

四、输出输入运算符重载

 1、输出运算符重载<<重载:他有俩个参数第一个是ostream类的引用,第二个参数是当前类的常量对象的引用;

  ostream & operator<<(ostream &os,const classType &obj)

{

    os <<"要输出的内容";

    return os;//为的是这中情况:cout<<r<<k;

}

 istream & operator>>(istream &is,classtype &obj)

{

is >>对象的数据成员;

return is;

}

 

#include<iostream>
#include<vld.h>
#include<string.h>
using namespace std;

class Array
{
public:
	friend ostream & operator<<(ostream &os,const Array & a)
	{
		os<<a.num;
		return os;
	}
	friend istream & operator>>(istream &is,Array &a)
	{
		is>>a.num ;
		return is;
	}
	Array():num(0)
	{}
	/*Array(int n)
	{
		cout<<"Array()"<<endl;
		str = new int[n];
		for(int i =0;i< n;++n)
		{
			str[i] = 0;
		}
	}*/
	Array(int x)
	{
       num = x;
	}
	Array& operator=(const Array& a)
	{
		cout<<"operator"<<endl;
		if(this == &a)return *this;
		delete []str;
		//int length = strlen(a.str);
		int length = sizeof(a)/sizeof(int);
		str = new int[length];
		return *this;
	}

	int & operator[](int index)
	{
		return str[index];
	}
	~Array()
	{
		//delete []str;在不是赋值函数的时候应该屏蔽点,否则出现内存错误
	}
private:
	int * str;
	int num;
};

int main()
{
	Array arry3;
	/*Array arry1(3);
	Array arry2(4);
	arry1 = arry2;*/
	//Array arry3(3);
	cin>>arry3;
	//cout<<arry3[0]<<endl;
	/*for(int i =0;i<3;++i)
	{
		cin>>arry3[i];
	}
	for(int i=0;i<3;++i)
	{
		cout<<arry3[i];
	}*/
	cout<<arry3<<endl;

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值