C++中赋值运算符重载返回值和参数类型问题

FuzhouJiang 2021-02-28 09:34:18
问题描述:对于自定义类型来说,我下方代码中的赋值运算符重载时函数返回值和参数类型为什么一定要是引用类型呢(若不是引用类型该程序会出错,错误提示在代码下方)?注释部分是我自己的理解,请各位大神帮忙看看有什么错误帮忙指正一下,先谢谢各位了。

#include<iostream>
using namespace std;
 
//赋值运算符重载
class Person
{
public:
    Person(int age)
    {
        m_Age = new int(age);
         
    }
 
     //参数必须是引用类型,若是值类型,在函数结束时会执行析构函数把指针(传入的p.m_Age)指向的内存空间释放掉.
    Person& operator=(Person &p)
    {
 
        //如果有未释放的堆区空间,先释放
        if (m_Age != NULL)
        {
            delete m_Age;
            m_Age = NULL;
        }
 
        m_Age = new int(*p.m_Age);
        return *this; 
    }
 
    ~Person()
    {
        if (m_Age != NULL)
        {
            delete m_Age;
            m_Age = NULL;
        }
    }
 
    int *m_Age;
};
 
void test01()
{
    Person p1(18);
    Person p2(20);
    Person p3(30);
 
    p3 = p2 = p1;
 
    //对于自定义数据类型,等号运算符重载返回值必须是引用类型
    //如上方代码相当于p3.operator=(p2.operator=(p1));,其中参数传递过程
即 Person &p = p2.operator=(p1);,如果operator= 函数返回的是值类型
    //则会先在内存中创建一个临时对象temp用于接收传递来的对象副本,然后用这个临时对象为引用p初始化
    //而临时对象生命周期很短,仅在当前语句结束后就释放其内存空间,而后再通过p访问临时变量的内存空间则是非法操作。
 
    cout << "p1的年龄为:" << *p1.m_Age << endl;
 
    cout << "p2的年龄为:" << *p2.m_Age << endl;
 
    cout << "p3的年龄为:" << *p3.m_Age << endl;
}
 
int main(void)
{
    test01();
    system("pause");
    return 0;
}


错误提示:

case1:当返回值不是引用类型时提示:

错误 C2679 二进制“=”: 没有找到接受“Person”类型的右操作数的运算符(或没有可接受的转换)

case2 :当参数不是引用类型时提示:

...全文
363 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
真相重于对错 2021-02-28
  • 打赏
  • 举报
回复
还有你的类没有自定义拷贝构造函数。 Person &p = p2.operator=(p1); 默认情况下没有拷贝构造函数,编译器会自动提供,它的实现就是把目标和原对象进行二进制的赋值。 这句话执行完毕p 和 p2 的age指向了同一个内存区域,所以当一个对象释放完毕后,下一个对象再次释放会出错。
真相重于对错 2021-02-28
  • 打赏
  • 举报
回复
返回值是可以的,你出错是因为你没有判断自我赋值 也就是T a; a=a;//这种形式 当出现这种形式的时候 你的operator= 先把a的age删除,在赋值给a,所以出错。 返回值的情况,它的缺点是多一次复制,效率不高
真相重于对错 2021-02-28
  • 打赏
  • 举报
回复
Person operator=(const Person &p)
FuzhouJiang 2021-02-28
  • 打赏
  • 举报
回复
引用 1 楼 真相重于对错 的回复:
返回值是可以的,你出错是因为你没有判断自我赋值 也就是T a; a=a;//这种形式
我添加了对自我赋值的判断之后,还是提示: 错误 C2679 二进制“=”: 没有找到接受“Person”类型的右操作数的运算符(或没有可接受的转换)

#include<iostream>
using namespace std;

//赋值运算符重载
class Person
{
public:
	Person(int age)
	{
		m_Age = new int(age);
	}

	//重载赋值运算符,用深拷贝解决浅拷贝的问题
	//在堆区开辟新的空间将被拷贝对象中指针成员所指向的值拷贝过来
	//参数必须是引用类型,若是值类型,在函数结束时会执行析构函数把指针(传入的p.m_Age)指向的内存空间释放掉.
	Person operator=(Person &p)
	{
                //判断是否自我赋值
		if(&p == this)
		{ 
			return *this;
		}
		
		//如果有未释放的堆区空间,先释放
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		
		//深拷贝
		m_Age = new int(*p.m_Age);
		return *this; 
	}

	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}

	int *m_Age;
};

void test01()
{
	Person p1(18);
	Person p2(20);
	Person p3(30);

	p3 = p2 = p1; 
	
	
	//如上方代码相当于p3.operator=(p2.operator=(p1));,其中参数传递过程即 Person &p = p2.operator=(p1);,如果operator= 函数返回的是值
	//则会先在内存中创建一个临时对象temp用于接收传递来的对象副本,然后用这个临时对象为引用p初始化
	//而临时对象声明周期很短,仅在当前语句结束后就释放其内存空间,而后再通过p访问临时变量的内存空间则是非法操作。
	

	
	cout << "p1的年龄为:" << *p1.m_Age << endl;

	cout << "p2的年龄为:" << *p2.m_Age << endl;

	cout << "p3的年龄为:" << *p3.m_Age << endl;
}


int main(void)
{
	test01();
	system("pause");
	return 0;
}



33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧