精华内容
下载资源
问答
  • c++中的拷贝构造函数
    千次阅读
    2022-05-18 23:50:28

    一、什么是拷贝构造函数

    拷贝构造函数,又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构造及初始化。

    其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制。

    此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。

    同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。 这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类 的另一个对象来初始化该对象的存储空间,这时所用的构造函数称为拷贝构造函数(Copy Constructor)。

    拷贝构造函数的参数一一采用引用。如果把一个真实的类对象作为参数传递到拷贝构造函数,会引起无穷递归 。

    在类中如果没有显式给出拷贝构造函数时,则C++编译器自动给出一个缺省的拷贝构造函数。

    如果有程序设计者定义的构造函数(包括拷贝构造函数),则按函数重载的规律,调用合适的构造函数。

    缺省的拷贝构造函数的特点:按位拷贝。

    二、调用拷贝构造函数的情形

    在C++中,下面三种对象需要调用拷贝构造函数(有时也称"复制构造函数"):

    1) 一个对象作为函数参数,以值传递的方式传入函数体;

    class Complex
    {
    };
    void Fun(Complex c1)
    {
    }
    
    int main()
    {
      Complex c1(1,2);
      Fun(c1);
    }

    2) 一个对象作为函数返回值,以值传递的方式从函数返回;

    Complex Fun()
    {
      Complex c(10,20);
      return c;
    }

    3) 一个对象用于给另外一个对象进行初始化(常称为赋值初始化);

    int main()
    {
      Complex c1(1,2);
      Complex c2(c1);
      Complex c3=c1;
    }

    当对象的成员变量中存在指针变量时,用存在的对象初始化新建对象时指针变量一同初始化,但这时调用一般拷贝构造函数(浅拷贝)会使新对象中的指针指向和初始化对象指针指向一致,那么当用来初始化的对象在释放内存时会释放掉指针指向的内存,而当新创建的对象释放时会出现程序错误,以为这个指针指向的内存被释放了两次。因此我们需要手动提供另一种拷贝构造函数(深拷贝).

    三、实现缺省的拷贝构造函数

    1.整形数据成员

    class Complex
    {
    private:
        int Real;
        int Image;
    public:
       //缺省构造
       //Complex() {}
       //构造函数
       Complex(int r=0,int i=0):Real(r),Image(i)
       {
       }
       //拷贝构造函数  不能够定义为const,否则无法对对象成员进行赋值
       Complex(const Complex &c):Real(c.Real),Image(c.Image)
       {
       }
    }
    
    int main()
    {
       Complex c1(1,2);
       Complex c2(c1);//c1对象初始化c2
       Complex c3=c1;//编译器可自动改写为Complex c3(c1);
    }
    class CDate
    {
      int year;
      int month;
      int day;
    public:
      //构造函数
      CDate(int y=1,int m=1,int d=1):year(y),month(m),day(d)
      {
      }
      //拷贝构造函数
      CDate(const CDate &cd):year(cd.year),month(cd.month),day(cd.day)
      {
      }
    };
    
    int main()
    {
      Cdate data(2022,5,12);
      Cdate datb(data);
    }

    2.char类型数组数据成员 

    const int len = 20;
    class CGoods
    {
      private
      char Name[len];
      int Amount;
      float Price;
      float Total;
    public:
      // 构造函数
      CGoods()
      {
       memset(Name,0,sizeof(Name));
       Amount = 0;
       Price = 0.0;
       Total = 0.0;
      }
      CGoods(const char *name,int amount,int price)
      {
       strcpy_s(Name,len,name);
       Amount = amount;
       Price= price;
       Total = Amount * Price;
      }
      //拷贝构造函数
      CGoods(const CGoos &cg):Amount(cg.Amount),Price(cg.Price),Total(cg.Total)
      {
       strcpy_s(Name,len,cg.Nmae);
      }
    };
    int main()
    {
      CGoods c1("wer",12,1235);
      CGoods c2(c1);
    }

    四、拷贝构造函数必须以引用的形式传递(参数为引用值)。

    当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。

    更多相关内容
  • C++中拷贝构造函数的定义  有一个参数的类型是其类类型的构造函数是为拷贝构造函数。如下:  X::X( const X& x);  Y::Y( const Y& y, int =0 );  //可以是多参数形式,但其第二个即后继参数都有一个默认值 ...
  • 原因:如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。...
  • 1.什么是拷贝构造函数拷贝构造函数嘛,当然就是拷贝和构造了。(其实很多名字,只要静下心来想一想,就真的是顾名思义呀)拷贝又称复制,因此拷贝构造函数又称复制构造函数。百度百科上是这样说的:拷贝构造函数...
  • 一、C++中拷贝构造函数的定义: 有一个参数的类型是其类类型的构造函数是为拷贝构造函数。 如下所示: X::X( const X& x); Y::Y( const Y& y, int =0 ); //可以是多参数形式,但其第二个即后继参数都有一个默认值 ...
  • 1. 拷贝构造函数 什么时候会调用拷贝构造函数 ? 使用一个已经创建好的对象来初始化一个新的对象。 Student mya("zhang3",22); //如果是在定义一个对象通过另一个对象来初始化,那么会调用拷贝构造函数 ...

    1.  拷贝构造函数

    什么时候会调用拷贝构造函数  ?

               使用一个已经创建好的对象来初始化一个新的对象。

        Student mya("zhang3",22);
                //如果是在定义一个对象通过另一个对象来初始化,那么会调用拷贝构造函数
        Student myb(mya);
        //等同于Student myb = mya;

            特点:   值传递的方式给函数参数传值

    代码示例如下:

    class Student{
    public:
        Student()
        {
            cout<<Student()<<endl;
        }
        Student(char *name,int age){
           this->name = new char[256];
           strcpy(this->name,name);
           this->age = age;
           cout<<Student(char *name,int age)<<endl;
        }
        //如果我们没有自己定义拷贝构造函数,编译器就会帮助我们自动生成默认的拷贝构造函数---浅拷贝--值的拷贝
    //    Student(Student &other) //Student &other = mya
    //    {
    //        this->name = other.name;
    //        this->age = other.age;
    //        cout<<Student(Student &other)<<endl;
    //    }
        //自定义深拷贝 --在进行值的拷贝的同时,也要给指针变量申请新的堆空间
        Student(const Student &other) //Student &other = mya
        {
            //申请堆空间
            this->name = new char[256];
            //值的拷贝
            strcpy(this->name,other.name);
            this->age = other.age;
           cout<<Student(Student &other)<<endl;
        }
        ~Student(){
            //析构函数一般用来  释放 成员的内存空间
            delete []name;
            cout<<~ Student()<<endl;
        }
        void show()
        {
            cout<<this->name<< <<this->age<<endl;
        }
    private:
        char *name;
        int age;
    };
    int main()
    {
        Student mya("zhang3",22);
        //如果是在定义一个对象通过另一个对象来初始化,那么会调用拷贝构造函数
        Student myb(mya);
        //Student myb = mya;
    
        return 0;
    }

    2.  赋值函数

               当一个类的对象对另一个对象进行直接赋值时会调用赋值函数

        Data mya;
        mya.setName("zhangsan");
        Data myb;
        //赋值重载
        myb = mya; //编译器会转换成 myb.operator=(mya)  

    如果程序员没有自定义赋值运算符函数。系统会调用自动生成的默认赋值函数(如下面代码注释部分)

    什么时候需要自定义赋值函数?

    如果类定义中存在指针或者引用变量或对象,对象与对象进行赋值时就会出现内存泄漏。

    为了防止这种情况发生我们就需要自定义赋值函数

    (我的理解就是   ->  当申请了堆空间的时候 )

    代码示例如下

    class Data
    {
    public:
    	Data(){
    		name = new char[256];
    	}
    	~Data(){
    		delete[]this->name;
    	}
    	
    	void setName(const char *name) {
    		strcpy(this->name,name);
    	}
    	/*
    	//如果没有自定义赋值函数,系统执行自动生成的默认赋值函数 ---(系统自动生成的赋值函数底层原型)
    	void operator=(Data &ra) //Data &ra = mya
    	{
    		this->name = ra.name;
    	} */
    	//系统调用默认的赋值函数会造成内存泄漏  /所以我们需要只需要自定义赋值函数
    	void operator=(Data &ra) //Data &ra = mya
    	{
    		strcpy(this->name, ra.name);
    	}
    private:
    	char * name; //姓名
    };
    int main()
    {
    	Data mya;
    	mya.setName("zhangsan");
    	Data myb;
    	//赋值重载
    	myb = mya; //编译器会转换成 myb.operator=(mya)  
    
    	return 0;
    }

    总结:

    当我们对两者不够了解时,很容易错写,错用。

    拷贝构造函数就是在对象被创建的时候调用的,而赋值函数只能被创建好的对象调用

    展开全文
  • 详解C++ 拷贝构造函数

    2021-01-19 23:44:42
    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于: 通过使用另一个同类型的对象来初始化新创建的对象。 复制对象把它作为参数传递给...
  • 本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数、什么情况下调用赋值运算符。最后,简单的分析了下深拷贝和浅拷贝的问题。有需要的朋友可以看下
  • C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象时,它...
  • 构造函数可以有多个,而拷贝构造函数只能有一个,因为拷贝构造函数的参数只能是当前类的一个对象,参数表是固定的,无法重载,若用户没有定义自己的辅助构造函数,系统会自动生成一个复制构造函数(浅拷贝构造函数,...

    C++中的构造函数

    • c++中的构造函数分为构造函数,和拷贝(复制)构造函数,相比于构造函数,复制构造函数使用更加方便,快捷。构造函数可以有多个,而拷贝构造函数只能有一个,因为拷贝构造函数的参数只能是当前类的一个对象,参数表是固定的,无法重载,若用户没有定义自己的辅助构造函数,系统会自动生成一个复制构造函数(浅拷贝构造函数,只能复制简单变量,一般需要自定义一个深拷贝构造函数,即完全拷贝),其作用是将参数的之赋予当前的对象.若用户自己定义了复制构造函数,系统则不会生成默认复制构造函数。用户自己定义的复制构造函数功能可以自己构造,不一定执行复制的功能。

    复制构造函数同构造函数的功能大体相同·,却又有不同之处,下面介绍复制构造函数在3中情况下的调用

    • 1.当用一个对象去初始化同类的另一个对象时,会引发复制构造函数的调用

    以下两条语句都会导致复制构造函数的调用

         Complex c1(c2);
         Complex c1=c2;
    

    这两条语句时等价的,其中第二句是初始化语句,不是赋值语句

    下面这一条语句不会调用复制构造函数,是赋值语句

         Complex c1,c2;
         c1=c2;
    

    2.作为形参的对象,使用复制构造函数初始化的
    以下语句可以证明

        #include<iostream>
        using namespace std;
        class A{
         public:
            A(){};//构造函数
             A(A&a)//复制构造函数
            {
                cout<<"Copy constructer called"<<endl;
            }
          };
          void Func(A a)//普通函数
         {
    
         }
         int main()
          {
          A b;
          Func(b);//此语句相当于是将b复制给Func(a)中的a,导致调用复制构造函数
          retur 0;
    
          }
    

    程序运行截图
    在这里插入图片描述

    3.如果函数返回的是类A的对象,那么函数返回时,类A的复制构造函数会被调用
    程序如下

         #include<iostream>
         using namespace std;
    
         class A{
         public:
           int v;
           A(int i){
               v=i;
            };//构造函数
            A(A&a)//复制构造函数
            {
                cout<<"Copy constructer called"<<endl;
             }
          };
           A a(4);
           A Func()//普通函数
           {
    
              return a;
           }
            int main()
            {
            cout<<Func().v<<endl;//此语句中的Func()是一个类A的对象,但是不是a,只是用a初始化。
            return 0;
    
          }
    

    在这里插入图片描述
    以上三种情况是比较常见的复制构造函数被调用的例子

    展开全文
  • 主要介绍了详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数的相关资料,这里提供实例帮助大家理解掌握这部分内容,需要的朋友可以参考下
  • C++中拷贝构造函数的四种调用方式

    千次阅读 2020-06-21 22:31:59
    代码拿着跑一跑就什么都知道了 #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> using namespace std;... 构造函数 */ Student(int age, string name) { this->age.

    代码

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<string>
    using namespace std;
    static int i = 0;
    class Student
    {
    private:
    	int age;
    	string name;
    public:
    	/*
    	构造函数
    	*/
    	Student(int age, string name)
    	{
    		this->age = age;
    		this->name = name;
    
    		cout << "构造函数" << endl;
    	}
    	/*
    	无参构造函数
    	*/
    	Student() { cout << "无参构造函数" << endl; }
    	/*
    	拷贝构造函数
    	*/
    	Student(const Student & stur)
    	{
    		age = stur.age;
    		name = stur.name;
    		cout << "拷贝构造函数" << endl;
    	}
    	/*
    	析构函数
    	*/
    	~Student()
    	{
    		cout << "析构函数" << endl;
    
    	}
    	void print()
    	{
    		cout << age << endl;
    	}
    };
    
    Student fun(int age, string name)
    {
    	Student stu(age, name);   // stu是局部变量,在函数执行完将会进行析构
    	return stu;//会存在Student temp = stu,在主调函数中如果有变量接受  temp的话就不会立刻释放
    }
    
    void fun2(const Student stur)
    {
    	cout << "fun2" << endl;
    }
    
    
    return 0;
    }
    

    四种调用方法

    int main()
    {
    	Student stu1(12,"lisi");
    
    #if 0
    	//第一种调用方式
    	Student stu2(stu1);
    
    	//第二种
    	Student stu3 = stu1;
    
    	//注:以下方式不行
    	 Student stu3;
    	 stu3 = stu1;// 这是先调用无参构造创建,然后再赋值
    #endif
    	//第三种作为函数的返回值时会存在  Student temp = stu;
    	fun(10, "张三");
    	cout << "fun执行完了" << endl;//temp在此之前被析构,相当于匿名对象,使用完就会被析构
    
    #if 0
    	Student stu4 = fun(11, "王五");//这种情况  stu4= 这一过程没有调用拷贝构造函数,而是直接将temp转正为stu4
    	cout << "fun执行完了" << endl;//temp被转正为stu4
    
    	//第四种,作为函数参数使用时
    	fun2(stu1);//存在Student stur = stu1
    
    #endif
    	

    运行结果

    方式1与2

    方式3  不用变量接收,执行完以后临时对象立刻被析构

     

    方式3  使用变量接受,临时对象转正

    方式4  存在Student stur = stu1

    展开全文
  • C++中拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对象创建出一个新的对象。从本质上讲,对象也是一份数据,因为它会占用内存。 严格来说,对象的创建包括两个阶段..
  • 拷贝构造函数C++最基础的概念之一,大家自认为对拷贝构造函数了解么?请大家先回答一下三个问题:1. 以下函数哪个是拷贝构造函数,为什么?X::X(const X&); X::X(X); X::X(X&, int a=1); X::X(X&, int a=1, b=2);...
  • C++拷贝构造函数的调用时机

    千次阅读 多人点赞 2022-04-14 17:30:22
    本章内容:C++拷贝构造函数的调用时机是?什么时候会调用拷贝构造函数
  • c++拷贝构造函数

    千次阅读 多人点赞 2019-06-28 16:22:40
    什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。 下面看一个类对象...
  • C++中拷贝构造函数的使用,帮助加深理解。
  • C++——拷贝构造函数详解

    千次阅读 2022-01-13 15:11:02
    C++——拷贝构造函数1拷贝构造函数的特点:2通过例子引入拷贝构造:3构造对象的时候使用引用返回与不使用引用返回的问题:3.1不使用引用返回3.2引用返回——从已经死亡的地址接收值不牢靠 1拷贝构造函数的特点: ...
  • 文章目录OOP拷贝构造函数浅拷贝与深拷贝 OOP 拷贝构造函数 A(const A & a); const:防止修改 &:不仅为了节省空间,更为了防止递归!这里是值传递。 #include <iostream> using namespace std; ...
  • 关键字explicit 修饰构造方法的关键字,加上了,就告诉编译器,不可以隐式初始化对象;不加就可以隐式初始化对象; 下面的代码是可以正常编译执行的,但是加了关键字explicit,编译就会错我,因为...拷贝构造函数如果
  • c++中拷贝构造函数

    千次阅读 2019-04-05 13:01:58
    #include"Head.h" class CStu { public: CStu() { } CStu(const CStu&) { ... /*以下4种会调用拷贝构造函数 CStu stNew(stu1); CStu stNew = stu1; CStu stNew = CStu(stu1); CSt...
  • C++中,我们使用拷贝构造函数来实现对象的复制。我们需要注意的是,在定义拷贝构造函数的时候,传入参数不能是传值参数,例如A(A other)。因为如果是传值函数,就会在拷贝构造函数内将形参复制为实参,而复制的...
  • 首先讲讲拷贝构造函数拷贝构造函数是先将传入的参数对象进行一次深拷贝,再传给新对象。这就会有一次拷贝对象的开销,并且进行了深拷贝,就需要给对象分配地址空间。 而移动构造函数就是为了解决这个拷贝开销而...
  • C++ 拷贝构造函数与赋值函数

    千次阅读 2019-02-20 14:09:46
    这里我们用类String 来介绍这两个函数: ...试想一下,假如形参是该类的一个实例,由于是传值参数,我们把形参复制到实参会调用拷贝构造函数,如果允许拷贝构造函数传值,就会在拷贝构造函数内调用拷贝构...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 144,077
精华内容 57,630
关键字:

c++中的拷贝构造函数