C++学习总结15 -- 拷贝构造和拷贝赋值

小记:静默如初,安之若素

1. 拷贝构造

1. 浅拷贝和深拷贝
1)定义:如果一个类中包含指针形式的成员变量,用缺省的拷贝构造函数只是复制指针变量本身,而没有复制指针所指向的内容,这种拷贝方式成为浅拷贝。
2)浅拷贝将会导致不同对象间的数据共享,同时会在析构函数中引发”double free“异常,因此就必须自己定义一个支持复制指针内容的拷贝构造函数,即深拷贝.

  2 using namespace std;
  3 
  4 class Integer
  5 {
  6 public:
  7   Integer(int data = 0)
  8     :m_data(new int(data))
  9     {
 10       //m_data = new int(data);
 11   }
 12   ~Integer(void)
 13   {
 14     cout<<"xigou hanshu"<<endl;
 15     delete m_data;
 16   }
 17   //Integer i2(i1)
 18   //i2.m_data = i1.m_data
 19   //缺省的拷贝构造函数(浅拷贝)
 20   /*Integer(const Integer& that)
 21   {
 22     m_data = that.m_data; 
 23   }*/
 24 
 25   //Integer i2(i1);
 26   //i2.data = new int(*i1.m_data);
 27   //自定义深拷贝构造
 28   Integer(const Integer &that)
 29   {
 30     m_data = new int(*that.m_data);
 31   }
 32 
 33   void print(void) const
 34   {
 35     cout << *m_data << std::endl;
 36   }
 37 
 38 private:
 39   int *m_data;//指针一定要注意最后释放,否则造成内存泄露
 40 };
 41 
 42 int main(int argc, char *argv[])
 43 {
 44   Integer i1(100);
 45   Integer i2(i1);//拷贝构造
 46 
 47   i1.print();
 48   i2.print();
 49 
 50   return 0;
 51 }

笔试题/练习:实现string类

  1 #include <iostream>
  2 #include <cstring>
  3 using namespace std;
  4 class String
  5 {
  6 public:
  7   //构造函数
  8   String(const char *str = "")//缺省
  9   { 
 10     m_str = new char[strlen(str) + 1];
 11     strcpy(m_str, str);
 12   }
 13   //析构函数
 14   ~String(void)
 15   {
 16     delete[] m_str;
 17   }
 18   //拷贝构造函数
 19   //浅拷贝
 20   //String (const String &that)
 21   //{
 22   //  m_str = that.m_str; 
 23   //}
 24   
 25   //深拷贝
 26   String (const String &that)
 27   {
 28     m_str = new char[strlen(that.m_str) + 1];
 29     strcpy(m_str, that.m_str);
 30   }
 31 private:
 32   char *m_str;
 33 public: 
 34   const char *c_str()const
 35   { 
 36     return m_str;
 37   }
 38 };
 39 int main(int argc, char* argv[])
 40 { 
 41   String s1 = "hello world!";
 42   cout << s1.c_str() << endl;
 43   String s2 = s1;
 44   cout << s2.c_str() << endl;
 45   return 0;
 46 }

2. 拷贝赋值

1)当编译器看到两个对象的赋值操作时,比如” i3=i2 “,会将其翻译成函数调用形式: ”i3.operator = (i2)“,该函数成为拷贝赋值操作符函数,由该函数完成两个对象的复制的过程。
2)缺省的拷贝赋值函数和缺省拷贝构造函数类型,也是浅拷贝,有**”double free“问题内存泄露**问题;
3)所以必须自己定义支持深拷贝的拷贝赋值操作符函数;
4)语法:

类名 & operator=(const 类名& that)
{
	if(&that != this)//防止自赋值
	{
		//释放旧资源
		//分配新资源(大小与新数据大小相同)
		//拷贝新数据
	}	
	return *this;//返回自引用
}
 #include<iostream>
  2 using namespace std;
  3 
  4 class Integer
  5 {
  6 public:
  7   Integer(int data = 0)
  8     :m_data(new int(data))
  9     {
 10       //m_data = new int(data);
 11   }
 12   ~Integer(void)
 13   {
 14     cout<<"xigou hanshu"<<endl;
 15     delete m_data;
 16   }
 17   //Integer i2(i1)
 18   //i2.m_data = i1.m_data
 19   //缺省的拷贝构造函数(浅拷贝)
 20   /*Integer(const Integer& that)
 21   {
 22     m_data = that.m_data; 
 23   }*/
 24 
 25   //Integer i2(i1);
 26   //i2.data = new int(*i1.m_data);
 27   //自定义深拷贝构造
 28   Integer(const Integer &that)
 29   {
 30     m_data = new int(*that.m_data);
 31   }
 32 
 33   void print(void) const
 34   {
 35     cout << *m_data << std::endl;
 36   }
 37 
 38   //i3 = i2;-->i3.operator=(i2)
 39   //i3.m_data = i2.m_data
 40   //类中缺省的拷贝赋值函数
 41   /*Integer& operator=(const Integer& that)
 42   {
 43     cout <<" 拷贝赋值操作符函数" << endl;
 44     m_data = that.m_data;
 45     return *this;
 46   }*/
 47   //i3 = i2;==>i3.operator=(i2)
 48   //*i3.m_data = *i2.m_data;
 49   //自定义深拷贝赋值函数
 50   Integer& operator=(const Integer &that)
 51   {
 52     if(&that != this)
 53     {
 54       delete m_data;
 55       m_data = new int;
 56       *m_data = *that.m_data;
 57     }
 58       return *this;
 59   }
 60 private:
 61   int *m_data;//指针一定要注意最后释放,否则造成内存泄露
 62 };
 63 
 64 int main(int argc, char *argv[])
 65 {
 66   Integer i1(100);
 67   Integer i2(i1);//拷贝构造
 68 
 69   i1.print();
 70   i2.print();
 71 
 72   Integer i3;//i3(i2)-->拷贝构造
 73   //i3.operator= (i2);
 74   i3 = i2;//拷贝赋值,存在问题:double free,内存泄露
 75   /*
 76     eg:
 77     int *i2 = new int(100);
 78     int *i3 = new int(0);
 79 
 80     i3 = i2;//i3原有的内存0泄露了,因为i3指向了i2
 81     *i2-->100
 82     *i3-->100
 83 
 84     delete i2;
 85     delete i3;
 86   */
 87   i3.print();
 88 
 89   return 0;
 90 }

笔试题/练习:实现string类
示例程序(拷贝构造和拷贝赋值):

 1 #include <iostream>
  2 #include <cstring>
  3 using namespace std;
  4 class String
  5 {
  6 public:
  7   //构造函数
  8   String(const char *str = "")//缺省
  9   { 
 10     m_str = new char[strlen(str) + 1];
 11     strcpy(m_str, str);
 12   }
 13   //析构函数
 14   ~String(void)
 15   { 
 16     delete[] m_str;
 17   }
 18   //拷贝构造函数
 19   //浅拷贝
 20   //String (const String &that)
 21   //{
 22   //  m_str = that.m_str; 
 23   //}
 24   
 25   //深拷贝
 26   String (const String &that)
 27   { 
 28     m_str = new char[strlen(that.m_str) + 1];
 29     strcpy(m_str, that.m_str);
 30   }
 31   //拷贝赋值
 32   //自定义深拷贝赋值操作函数
 33   //s2==>hello
 34   //s3==>hello world
 35   //s2 = s3; ==>s2.operator(s3)
 36   String& operator=(const String &that)
 37   { 
 38     if(&that != this)//防止自赋值
 39     { 
 40       delete[] m_str;//释放旧资源
 41       m_str = new char[strlen(that.m_str)+1];//释放旧资源
 42       strcpy(m_str, that.m_str);//拷贝新数据
 43     }
 44     return *this;//返回自引用
 45   }
 46 private:
 47   char *m_str;
 48 public: 
 49   const char *c_str()const
 50   { 
 51     return m_str;
 52   }
 53 };
 54 int main(int argc, char* argv[])
 55 { 
 56   String s1 = "hello";
 57   cout << s1.c_str() << endl;
 58   String s2 = s1;
 59   cout << s2.c_str() << endl;
 60 
 61   String s3 = "hello world";
 62   //s2.operator=(s3)
 63   s2 = s3;//拷贝赋值
 64   cout << s2.c_str() << endl;
 65   return 0;
 66 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值