无涯教程-C++ 复制构造函数

50 阅读3分钟

复制构造函数是重载(overloaded)构造函数,用于从另一个对象声明和初始化一个对象。

复制构造函数两种类型

  • 默认副本构造函数     -  编译器定义默认副本构造函数。如果用户未定义副本构造函数,则编译器将提供其构造函数。
  • 用户自定义构造函数 -  程序员定义用户定义的构造函数。
C++ Copy Constructor

自定义构造函数语法

Class_name(const class_name &old_object);

请考虑以下情况:

class A
{
    A(A &x)// 复制构造函数。
   {
      //复制构造函数.
   }
} 

在上述情况下,可以通过以下方式调用复制构造函数:

C++ Copy Constructor

让我们看一下复制构造函数的简单示例。

//复制构造函数的程序。

#include <iostream>
using namespace std;
class A
{
   public:
    int x;
    A(int a)               //参数化构造函数。
    {
      x=a;
    }
    A(A &i)              //复制构造函数
    {
        x = i.x;
    }
};
int main()
{
  A a1(20);              //调用参数化构造函数。
  A a2(a1);               // 调用复制构造函数。
  cout<<a2.x;
  return 0;
}

输出:

20

在以下情况下将调用复制构造函数:

  • 当我们使用另一个具有相同类类型的现有对象初始化该对象时。例如,Student s1 = s2,其中Student是类。
  • 当同一类类型的对象通过值作为参数传递时。
  • 当函数按值返回相同类类型的对象时。

构造函数两种类型

  • 浅拷贝
  • 深拷贝

浅拷贝

  • 默认副本构造函数只能生成浅拷贝。
  • 浅拷贝定义为通过按原样复制所有成员变量的数据来创建对象副本的过程。

让我们通过一个简单的例子来理解这一点:

#include <iostream>

using namespace std;

class Demo { int a; int b; int p; public: Demo() { p=new int; } void setdata(int x,int y,int z) { a=x; b=y; p=z; } void showdata() { std::cout << "value of a is : " <<a<< std::endl; std::cout << "value of b is : " <<b<< std::endl; std::cout << "value of p is : " <<p<< std::endl; } }; int main() { Demo d1; d1.setdata(4,5,7); Demo d2 = d1; d2.showdata(); return 0; }

输出:

value of a is : 4   
value of b is : 5  
value of *p is : 7 
C++ Copy Constructor

在上述情况下,程序员没有定义任何构造函数,因此,语句Demo d2 = d1;调用编译器定义的默认构造函数。默认构造函数创建现有对象的浅拷贝。因此,两个对象的指针p指向相同的存储位置。因此,当释放一个字段的内存时,另一个字段的内存也会自动释放,因为两个字段都指向相同的存储位置。用户创建深拷贝的自定义构造函数可以解决此问题。

深拷贝

深拷贝为拷贝动态分配内存,然后拷贝实际值,源和拷贝都有不同的存储器位置。这样,源和副本都是不同的,并且不会共享相同的内存位置。深拷贝要求我们编写用户定义的构造函数。

让我们通过一个简单的例子来理解这一点。

#include <iostream>
using namespace std;
class Demo
{
    public:
    int a;
    int b;
    int *p;
</span><span class="typ">Demo</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    p</span><span class="pun">=</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">Demo</span><span class="pun">(</span><span class="typ">Demo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">d</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> d</span><span class="pun">.</span><span class="pln">a</span><span class="pun">;</span><span class="pln">
    b </span><span class="pun">=</span><span class="pln"> d</span><span class="pun">.</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
    p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*(</span><span class="pln">d</span><span class="pun">.</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> setdata</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> x</span><span class="pun">,</span><span class="kwd">int</span><span class="pln"> y</span><span class="pun">,</span><span class="kwd">int</span><span class="pln"> z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    a</span><span class="pun">=</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
    b</span><span class="pun">=</span><span class="pln">y</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">p</span><span class="pun">=</span><span class="pln">z</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> showdata</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"value of a is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">a</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"value of b is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">b</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"value of *p is : "</span><span class="pln"> </span><span class="pun">&lt;&lt;*</span><span class="pln">p</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

}; int main() { Demo d1; d1.setdata(4,5,7); Demo d2 = d1; d2.showdata(); return 0; }

输出:

value of a is : 4   
value of b is : 5   
value of *p is : 7   
C++ Copy Constructor

在上述情况下,程序员已经定义了自己的构造函数,因此语句Demo d2 = d1;调用用户定义的副本构造函数。它创建值类型数据和指针p指向的对象的深拷贝。深拷贝不会创建引用类型变量的副本。

参考链接

www.learnfk.com/c++/cpp-cop…