类中深浅拷贝、返回this指针、返回局部变量地址联合易错点

1:不要返回局部变量的地址,再对其进行解引用

因为,当这个局部变量出了他所在的代码段以后,值会被丢弃。这样返回的值只会在第一次返回时被保留,第二次就会乱值。

class Person
{
public:
	int m_age;
	int* m_height;
	Person(int age, int height)
	{
		m_age = age;
		int a = height;
		m_height = &a; // 对m_height传入了a的地址,而a出了这个代码段其值就会被抛弃
	}

};
void test()
{
	Person p1(10,160);
	cout << "p1的height是:" <<* p1.m_height <<"  第一次是对的"<<endl;    //第一次是对的
	cout << "p1的height是:" << *p1.m_height << "  第二次是对的" << endl;  //第二次是错的
;
}

//主函数
 int main()
{
	 test();
	system("pause");
	return 0;
}

结果:

p1的height是:160  第一次是对的
p1的height是:140842  第二次是错的

**解决办法:**创建一个堆区位置 new int ()

Person(int age, int height)
	{
		m_age = age;
		m_height = new int(height);  //new 关键字返回的是地址
	}

2.深拷贝与浅拷贝的关系

该问题出错主要在于指针的释放上,
当采用系统默认给出的拷贝构造函数时,p1和p2(copy)的m_height指针会指向同一块堆区内存,故当运行析构函数释放这块内存时,会导致重复释放

错误代码

class Person
{
public:
	int m_age;
	int* m_height;
	Person(int age, int height)
	{
		m_age = age;
		m_height = new int(height);  
	}
	~Person()
	{
		if (m_height != NULL)  //若不编写拷贝构造函数而使用系统的默认构造函数,p2的m_height指针会和p1的指针指向同一块内存
			                   // 会在释放时重复释放
		{
			delete m_height;
			m_height = NULL;
		}
	}

};
void test()
{
	Person p1(10,160);
	Person p2(p1);
	
;
}

//主函数
 int main()
{
	 test();
	system("pause");
	return 0;
}

错误原理如下图
在这里插入图片描述
解决办法:重新定义拷贝构造函数,开辟新的堆区空间

// 深拷贝
class Person
{
public:
	int m_age;
	int* m_height;
	Person(int age, int height)
	{
		m_age = age;
		m_height = new int(height);  
	}
	Person(const Person& p) // 拷贝构造函数
	{
		m_height = new int(*p.m_height); // 为这个值重新开辟一个地址
	}
	~Person()
	{
		if (m_height != NULL)  
		{
			delete m_height;
			m_height = NULL;
		}
	}

};
void test()
{
	Person p1(10,160);
	Person p2(p1);
	cout << "p1的身高是:" << *p1.m_height << endl;
	cout << "p2的身高是:" << *p2.m_height << endl;
;
}

//主函数
 int main()
{
	 test();
	system("pause");
	return 0;
}

3.返回 * this指针时,为何要使用 & 来接收

构建一个场景:有一个人p1的年龄是10,p2年龄也是10,现在想让p2的年龄等于他自身的年龄加上p1的年龄,用return this指针来完成:
正确的代码 : 使用Person & 来接收对象

class Person
{
public:
	int m_age;
	Person(int age)
	{
		m_age = age; 
	}
	Person & Addage(Person &p)
	{
		this->m_age += p.m_age; 
		return *this;

	}

};
void test()
{
	Person p1(10);
	Person p2(p1);
	p2.Addage(p1);
	cout << "p1的年龄是:" << p1.m_age<< endl;
	cout << "p2的年龄是:" << p2.m_age << endl;
;

结果:

p1的年龄是:10
p2的年龄是:20

若使用 Person 来接收

class Person
{
public:
	int m_age;
	Person(int age)
	{
		m_age = age; 
	}
	Person Addage(Person &p)
	{
		this->m_age += p.m_age; 
		return *this;

	}

};
void test()
{
	Person p1(10);
	Person p2(p1);
	p2.Addage(p1).Addage(p1).Addage(p1);  // 不管加多少 p2.age结果依然是20 
	cout << "p1的年龄是:" << p1.m_age<< endl;
	cout << "p2的年龄是:" << p2.m_age << endl;
;
}

是因为 若不用Person& 来接收,则会导致返回的 * this 产生一个新的p2,这个p2会自己使用默认的拷贝函数,自己占用一个新的位置,我们称他为 p2 ’ ,(注意!!这与上一个深浅拷贝问题不同,这个是对象自己去拷贝一个新位置,相当于是问题2中p1和p2的关系)

此时p2’因为没有在test函数中被接收, 所以出了 person addage 代码段后 会被自动销毁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值