题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数
class CMyString
{
public:
CMyString(char* p_Data = NULL);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
1.题目分析
1.1 那些c++类中的函数
一个c++类中常见的有构造函数、拷贝构造、赋值运算符重载、析构,其中拷贝构造、赋值运算符重载默认使用编译器浅拷贝(值拷贝,简单的赋值);
构造函数和析构函数:创建对象时,初始化赋值用;编译器自动调用;编译器会提供,但是为空实现
拷贝构造:什么时候会用到拷贝构造?三种情况:用一个创建完的对象初始化新对象person p1(p2)、值传递方式给函数传参、值传递方式返回局部对象;什么时候需要深拷贝呢?当属性有在堆区开辟的,即类中含指针、new操作;此时可能造成多个指针指向同块内存,在析构时重复释放;
运算符重载:对已有的运算符重新定义,赋予新功能;本题中赋值运算符函数类内含指针,涉及到深拷贝;
1.2 标题类和对象中直接赋值对象p2 = p1行不行?
情况1:如果类中没有开辟在堆区的成员或属性(不用new,无指针),可以直接赋值,如下程序运行通过;
class person{
public:
person( int age){
m_age = age;
}
int m_age;
};
void test(){
person p(18);
person p2(20);
person p3(30);
p3 =p2 = p;
cout<<"年龄= "<<p.m_age<<endl; //18
cout<<"年龄= "<<p2.m_age<<endl; //18
cout<<"年龄= "<<p3.m_age<<endl; //18
}
情况2:如果类中有开辟在堆区的成员或属性,不可以直接赋值,因为在创建不同对象p1、p2时,在堆区会开辟两块新空间,简单的赋值p1 = p2会造成两个指针指向同块内存,在析构时重复释放;
#1.2.1 如何进行深拷贝
针对情况 2,需要深拷贝来解决问题,步骤:
1.首先判断p2 在堆区是否有数据,若有先释放;
2.其次new一个新空间;这样使用 = 时才会避免内存重复释放;
3.扩展:使用连续赋值 p3 = p2 = p1;要注意重载运算符函数的返回值;
程序如下:
class person{
public:
person( int age ){
m_age = new int( age); //new int 返回int *
}
//赋值运算重载 operator=
//连续赋值需要注意返回值,要用引用才能返回真正的自己;不用引用相当按照自身,调用拷贝构造函数(编译器自动给的值拷贝),创建一个新的副本
//参数传入用引用传递,如果用值传递相当于传入复制品,即需要调用一次复制构造函数,无益
person& operator= (person &p){
//编译器浅拷贝
// m_age = p.m_age;
//怎么进行深拷贝,首先p2(20)创建时堆区上已经有数据了;先判断有无数据,释放干净
if(m_age != nullptr){
delete m_age;
m_age = nullptr;
}
//其次,深拷贝,创建块堆区
m_age = new int(*p.m_age);
//返回对象本身,用this指针;解引用,就是对象本身
return *this;
}
~person(){
if(m_age != nullptr){
delete m_age;
m_age = nullptr;
}
}
int *m_age; //加*,就要开辟到堆区
};
void test(){
person p(18);
person p2(20);
person p3(30);
p3 =p2 = p; //赋值运算符需要重载,进行深拷贝解决浅拷贝问题;
cout<<"年龄= "<<*p.m_age<<endl;
cout<<"年龄= "<<*p2.m_age<<endl;
cout<<"年龄= "<<*p3.m_age<<endl;
}
2.回归本题
//返回值
//函数书写
//传入参数
CMyString& CMyString:: operator = (const CMyString &str){
if(this == &str) return *this;
if(m_pData != nullptr){
delete[]m_pData;
m_pData = nullptr;
}
m_pData = new char [strlen(str.m_pData)+1];
copystr(m_pData,str.m_pData);
return *this;
}
如有错误,欢迎指正*****