首页 > C++ 拷贝构造函数和重载赋值运算符的区别

C++ 拷贝构造函数和重载赋值运算符的区别

文章目录

      • 拷贝构造函数
      • 重载赋值运算符

赋值运算符和拷贝构造函数最大区别是赋值运算符没有新的对象生成,而拷贝构造函数会生成新的对象。

为了更加形象 准确得描述 赋值运算符和拷贝构造函数得区别,将详细通过代码展示两者之间得差异。

拷贝构造函数

首先从构造函数说起,在C++面向对象的设计中,每一个对象代表一个抽象集合的实体,此时每一个实体在当前运行的进程中是需要对应的内存空间,即对象存在则有空间。为此,C++引入构造函数来实例化对象,并让编译器为该对象向操作系统申请对应的空间,从而能够存在于操作系统之中。

拷贝构造函数则是为了将老对象的数据成员一一赋值给新的对象数据成员的一种构造函数,即拷贝构造函数的结果和构造函数一致,都是有新的对象生成。

查看如下代码:

#include 
using namespace std;class A{ 
public:A(){  cout << "default constructor " << endl;  }A(int a) { num=a;cout << "constructor with param" << endl; }A(const A &a){ num=a.num;cout << "copy constructor " << endl;}~A(){  cout << "destructor " << this->num << endl; }void print(){ cout << this->num << endl;}private:int num;};
void para_copy(A &a)
{ 
}
int main()
{ A a(100); // 重载构造函数A a1=a; //拷贝构造函数a1.print();A c;//默认构造函数return 0;
}

输出如下:

constructor with param //a 重载构造
copy constructor //a1 拷贝构造
100
default constructor //c默认构造
destructor 0 //c析构
destructor 100 //a1析构
destructor 100 //a析构

拷贝构造函数调用场景如下:

  • 我们如上代码中 一个对象由另一个对象来初始化
  • 对象作为函数参数
  • 对象作为函数返回值

    关于对象作为函数参数以及返回值时调用的拷贝构造函数,查看代码如下
    #include 
    using namespace std;class A{ 
    public:A(){  cout << "default constructor " << endl;  }A(int a) { num=a;cout << "constructor with param" << endl; }A(const A &a){ num=a.num;cout << "copy constructor " << endl;}~A(){  cout << "destructor " << this->num << endl; }void print(){ cout << this->num << endl;}private:int num;};
    void param_copy(A a)
    { cout << "param obj" << endl;
    }
    A return_value()
    { A d(0);cout << "return obj" << endl;return d;
    }
    int main()
    { A c;param_copy(c);return_value();return 0;
    }
    
    输出如下
    default constructor  //c 默认构造
    copy constructor // 对象做参数,拷贝构造到临时对象
    param obj
    destructor 0 // 析构掉临时对象
    constructor with param //函数return_value中 d 对象使用了重载构造函数
    return obj 
    destructor 0 //析构掉 d对象 ,局部变量
    destructor 0 //析构掉 c对象
    

关于深拷贝和浅拷贝的描述如下:

  1. 通常,默认生成的拷贝构造函数和赋值运算符,只是简单的进行值的复制。如果类的数据成员有指针,仅仅通过值传递进行拷贝构造的话会造成两个对象的成员指针指向同一块内存,当两个对象析构的时候会对同一个内存释放两次,从而会造成指针空悬。

  2. 深拷贝即以上第二种情况,数据成员中有指针变量的时候拷贝构造函数使用深拷贝,即构造函数中重新指定初始化对象的地址空间。

    代码如下:

    #include 
    using namespace std;class A{ 
    public:A(){  p=new int(10);cout << "default constructor " << endl;  }//A(int a) {num=a;cout << "constructor with param" << endl; }A(const A &a){ num=a.num;p=new int(10);*p=*(a.p);cout << "copy constructor " << endl;}~A(){  cout << "destructor " << this->num << endl; }void print(){ if(p!=NULL){ delete p;cout << this->num << endl;}}private:int num;int *p;};
    void param_copy(A a)
    { cout << "param obj" << endl;
    }
    int main()
    { A c;A b(c);return 0;
    }
    

重载赋值运算符

赋值运算符和拷贝构造函数最大区别即是赋值运算符没有新的对象生成,而拷贝构造函数会生成新的对象。

#include 
using namespace std;class Person
{ 
public:Person(){ }Person(const Person& p){ cout << "Copy Constructor" << endl;}Person& operator=(const Person& p){ cout << "Assign" << endl;return *this;}private:int age;string name;
};void f(Person p)
{ return;
}Person f1()
{ Person p;return p;
}int main()
{ Person p;Person p1 = p;    // Acout <<" p1 addr " <<  &p1 << endl;Person p2;cout <<" p2 addr " <<  &p2 << endl;p2 = p;           // Bcout <<" p2 addr after asign " <<  &p2 << endl;f(p2);            // C f函数参数cout <<" p2 addr after asign " <<  &p2 << endl;p2 = f1();        // D f1返回值为改对象,则先进行拷贝构造,在将返回的对象赋值给p2cout <<" p2 addr after asign " <<  &p2 << endl;Person p3 = f1(); // E 生成新对象,则为拷贝构造函数cout <<" p3 addr " <<  &p3 << endl;getchar();return 0;
}

输出如下:

Copy Constructor
Assign
Copy Constructor
Copy Constructor
Assign
Copy Constructor

更多相关:

  •   1 //简单重写原型对象: 2 3 //一个构造函数Person 4 function Person(){ 5 6 } 7 //重写Person的原型 8 //把Person的原型赋值给一个新的对象 是我们重写的过程 9 Person.prototype={ 10 // 对于构造器 如果我们...

  • 点云PCL免费知识星球,点云论文速读。文章:DSP-SLAM: Object Oriented SLAM with Deep Shape Priors作者:Jingwen Wang Martin Runz Lourdes Agapito编译:点云PCL代码:https://github.com/JingwenWang95/DSP-S...

  • RAM缓存 新RAM缓存算法(CLFUS) 新的RAM缓存使用的创意来自许多缓存替换策略和算法,包括LRU,LFU,CLOCK,GDFS及2Q,它被命名为时钟周期内最小频繁使用大小算法CLFUS(Clocked Least Frequently Used by Size)。它避开了任何专利算法,具有如下特性: 均衡最近性(Rec...

  • MP4 |视频:AVC,1280×720 30 fps |音频:AAC,48 KHz,2 Ch |时长:2h 12m 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:560M C4D是一个有抱负的运动图形艺术家和设计师的重要工具。借助C4D,您可以使用3D对象、动态效果和动画来增强运动图形、模型和可视化效果。本课...

  • 文章目录先说问题:再说解决尝试1:尝试2(该尝试建议先在自己环境搭配对应业务测试通过后再现场尝试): 感谢 学无止境996同学的陪伴和vigourtyy美丽女友的支持,直到这个解决问题的深夜 先说问题: ceph 12.2.1生产环境:3副本 tier + 3副本data 机房在拥有业务的情况下重启集群交换机,产生如下场景...

  • 这周主要学习了java中的类和对象的知识点,发现和C++中的类和对象极为相似,对于类和对象的概念理解起来也简单。同时在自学的过程中也把类的知识重新复习巩固了一下(如类的三大特征:继承,封装和多态,构造,成员对象的访问权限,构造,无参有参函数的调用等),同时也了解到一些新的概念,比如类对象创建和引用占据堆内存和栈内存,输出对象时默认调...

  • 草色新雨中, 松声晚窗里。之前我们学习 Power Query 都是用鼠标就完成了很多复杂的操作。虽然 PowerQuery 已经将大部分常用功能内置成到功能区。基本能完成我们大部分的报表自动化功能。但是总有些复杂的或者个性化的问题是开发团队没有预先想到的,这时我们就需要学习 M 语言。一、M 语言在哪里?M语言的函数公式有三个地...

  • 前言从2020年3月份开始,计划写一系列文档--《小白从零开始学编程》,记录自己从0开始学习的一些东西。第一个系列:python,计划从安装、环境搭建、基本语法、到利用Django和Flask两个当前最热的web框架完成一个小的项目第二个系列:可能会选择Go语言,也可能会选择Vue.js。具体情况待定,拭目以待吧。。。基本概念表达式表...

  • 1.1函数1.1.1什么是函数函数就是程序实现模块化的基本单元,一般实现某一功能的集合。函数名:就相当于是程序代码集合的名称参数:就是函数运算时需要参与运算的值被称作为参数函数体:程序的某个功能,进行一系列的逻辑运算return 返回值:函数的返回值能表示函数的运行结果或运行状态。1.1.2函数的作用函数是组织好的,可重复使用的,用来...

  • 原标题:基于Python建立深度神经网络!你学会了嘛?图1 神经网络构造的例子(符号说明:上标[l]表示与第l层;上标(i)表示第i个例子;下标i表示矢量第i项)单层神经网络图2 单层神经网络示例神经元模型是先计算一个线性函数(z=Wx+b),接着再计算一个激活函数。一般来说,神经元模型的输出值是a=g(Wx+b),其中g是激活函数(...

  • 在学习MySQL的时候你会发现,它有非常多的函数,在学习的时候没有侧重。小编刚开始学习的时候也会有这个感觉。不过,经过一段时间的学习之后,小编发现尽管函数有很多,但是常用的却只有那几个。今天小编就把常用的函数汇总一下,为大家能够能好的学习MySQL中的函数。MySQL常使用的函数大概有四类。时间函数、数学函数、字符函数、控制函数。让我...