【C++】五、拷贝构造与赋值构造


1.拷贝构造

1.1 为什么存在

  • 当类的数据成员中没有指针类型的变量时,直接对两个对象进行赋值没有问题。
  • 但是一旦类的数据成员含有指针变量,那么直接对这两个对象进行赋值操作之后,这两个对象的指针都将指向同一块内存。这时,一旦其中一个对象生存期结束,释放该内存,那么另一个对象的指针就变成了野指针!这对程序危害很大

1.2 定义

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。
  • 复制对象把它作为参数传递给函数。
  • 复制对象,并从函数返回这个对象。

2.赋值构造

什么时候调用拷贝构造,什么时候调用赋值构造呢??当出现下面两种情况的时候调用赋值构造

  1. 对象直接赋值给另一个对象,且接受值的对象已经初始化过
  2. 对象以值传递方式从函数返回,且接受返回值的对象已经初始化过

3.代码

赋值构造与拷贝构造原理类似,两个放在一起对比,就可以把知识闭环成体系,加深理解

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
   	  Line( );
      Line( int len );             // 简单的构造函数
      Line( const Line &obj);      // 拷贝构造函数,会覆盖默认拷贝构造函数
      Line& operator= (const Line& a);      //赋值构造函数
      ~Line();                     // 析构函数
      
      //注:默认的拷贝构造是位复制,即复制地址;重写后的是按值复制 
 
//   private:
      int *x;
};

Line::Line()
{
    cout << "调用默认构造函数" << endl;
    x = new int;
    *x = 10;
    printf ("stack address: %x, point: %x, value: %d\n", this, x, *x);
}
// 成员函数定义,包括构造函数
Line::Line(int value)
{
    cout << "调用参数构造函数" << endl;
    // 为指针分配内存
    x = new int;
    *x = value;
    printf ("stack address: %x, point: %x, value: %d\n", this, x, *x);
}

Line::Line(const Line &obj)
{
    cout << "调用拷贝构造函数并为指针 x 分配内存" << endl;
    x = new int; //指针 
    *x = *obj.x; // 拷贝值

    printf ("stack1 address: %x, point: %x, value: %d\n", this, x, *x);
}
Line & Line::operator=(const Line &obj)
{
    cout << "调用赋值构造函数并为指针 x 分配内存" << endl;
    x = new int; //指针 
    *x = *obj.x; // 拷贝值

    printf ("stack2 address: %x, point: %x, value: %d\n", this, x, *x);
}


Line::~Line(void)
{
    printf ("释放内存 address: %x, point: %x, value: %d\n", this, x, *x);
    delete x;
}

void display(Line obj)
{
	//在这个方法里面obj是副本,所以会调用一下拷贝构造函数初始化副本
	//初始化完之后,进行业务处理,用完之后就释放掉了 
   cout << "line 值 : " << *obj.x <<endl;
}
 
Line newObj(void)
{
   Line line1(10);
   printf ("stack3 address: %x, point: %x, value: %d\n", &line1, line1.x, *line1.x);
   return line1;
}

int main( )
{
   
   //1 浅拷贝 
   Line line1(10);//1.0 普通构造函数 
   printf ("global.line1 address: %x, point: %x, value: %d\n", &line1, line1.x,*line1.x);
   cout << "===========" << endl;
   //【注意】 !!! 下面两行不会调用拷贝构造,但是会调用赋值构造! 
   Line line2;
   line2 = line1; // 1.1 调用赋值构造函数 【赋值构造情景1】 

//   Line line2 = line1; // 1.2 调用拷贝构造函数【普通】 
   printf ("global.line2 address: %x, point: %x, value: %d\n", &line2, line2.x,*line2.x);
   cout << "===========" << endl;
   Line line3(line1); //1.3 调用拷贝构造函数【普通】 
   printf ("global.line3 address: %x, point: %x, value: %d\n", &line3, line3.x,*line3.x);
   cout << "===========" << endl;
   display(line1); //1.4 调用拷贝构造【副本】:方法里面是个副本,因要生成副本所以肯定要拷贝构造了 
   printf ("global.line1 address: %x, point: %x, value: %d\n", &line1, line1.x,*line1.x);
   cout << "===========" << endl;
   line2 = newObj();//1.5 调用赋值构造函数 【赋值构造情景2】 
   printf ("global.line2 address: %x, point: %x, value: %d\n", &line2, line2.x,*line2.x);
   cout << "===========" << endl;
   
   
   //2 深拷贝.....
    
   
   return 0;
}

4.参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值