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 代码段后 会被自动销毁。