C++构造函数及复制构造函数的学习心得

一些基本知识点:

构造函数:

  1. 对象生成时构造函数自动被调用,对象一旦生成,就在也不能在其上执行构造函数。
  2. 若自己定义的构造函数带参数,则声明对象时也需要带参数,缺省函数除外。

复制构造函数起作用的三种情况:

  1. 当用一个对象去初始化同类的另一个对象时 如 Test a1=a2,区别于赋值 Test a1,a2;a1=a2;
  2. 如果某函数有一个参数是类 A 的对象,那么该函数被调用时,类A的复制构造函数将被调用;
  3. 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用。

C++产生临时对象的三种情况:

  1. 类型转换;
  2. 以值的方式给函数传参(可对应上面三种情况的2);注意如果是按引用传递,则不会生成临时变量。
  3. 函数需要返回一个对象时(对应3)。

下面是一个具体实例:

#include<iostream>
#include<windows.h>
using namespace std;

class CRectangle
{
      private:
              int w,h;
              static int nTotalArea;
              static int nTotalNumber;
      public:
             CRectangle(int w_,int h_);
             
             ~ CRectangle();
             static void PrintTotal();
             CRectangle  AddOne();
            
};

CRectangle::CRectangle(int w_,int h_)
{
                           w=w_;
                           h=h_;
                           nTotalNumber ++;
                           nTotalArea +=w*h;
                           cout<<"constructor called"<<endl;
}

CRectangle::~CRectangle()
{

                         nTotalNumber --;
                         nTotalArea -=w*h;
                         cout<<"destructor called"<<endl; 
}

CRectangle   CRectangle::AddOne()
{
           this->w ++;
           return *this;
}



void CRectangle::PrintTotal()
{
     cout<<nTotalNumber<<","<<nTotalArea<<endl;
}

int CRectangle::nTotalNumber=0;
int CRectangle::nTotalArea=0;

int main()
    {
        CRectangle r1(3,3),r2(2,2);
        r2=r1.AddOne();
        
        CRectangle::PrintTotal();
        r1.PrintTotal();  
        
        system("pause");
        return 0; 
       
    }
     

运行结果如下

 在执行r2=r1.AddOne()时,由于AddOne函数返回对象类型,因此会调用复制构造函数生成临时的隐藏的CRectangle对象。而临时对象在消亡时会调用析构函数,减少nTotalNumber和nTotalArea的值,可是这些临时对象在生成时却没有增加它们的值,因此结果不是2,13,变成了1,1。要避免临时变量的影响,可以自己为CRectangle写一个复制构造函数,在里面改变nTotalNumber和nTotalArea的值。

CRectangle ::CRectangle(CRectangle & r)
{
           w=r.w;
           h=r.h;
           nTotalNumber ++;
           nTotalArea +=w*h;
           cout<<"copy constructor called"<<endl;
}

但是编译报错

仔细检查后发现是函数AddOne返回类型出错,与复制构造函数所需参数类型不匹配。

修改前 CRectangle   CRectangle::AddOne() 修改后 CRectangle  &  CRectangle::AddOne()

运行结果

 可以看到,并没有调用复制构造函数,这是因为AddOne函数返回类型是引用,而不是对象类型。

注意,如果修改main函数如下

int main()
    {
        CRectangle r1(3,3),r2(2,2),r3=r1.AddOne();//调用AddOne函数对r3初始化
        CRectangle::PrintTotal();
        r1.PrintTotal();  
        system("pause");
        return 0; 
     }

运行结果发生变化

这里调用了一次复制构造函数对r3进行初始化,但是没有生成临时对象。关于临时变量详细讲解可参考https://www.cnblogs.com/avril/archive/2010/10/20/1856320.html

猜你喜欢

转载自blog.csdn.net/qq_41381865/article/details/81334130