C++ 拷贝构造函数和赋值运算符

Wesley13
• 阅读 711

  这篇文章主要介绍拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数,什么情况下调用赋值运算符。    

  拷贝构造函数和赋值运算符

在默认情况下(用户没有定义,但是也没有显示的删除),编译器会自动隐式生成一个拷贝构造函数和赋值运算符,但用户可以使用delete来指定不生成拷贝构造函数和赋值运算符,这样的对象就不能通过值传递,也不能进行赋值运算

 1 #include <iostream>
 2 
 3 using namespace std;
 4 class Person {
 5 public:
 6     Person():{}
 7     Person(const Person& p) = delete;
 8     Person& operator= (const Person& p) = delete;
 9 
10     void SetName( string  strName ) 
11     {
12         name = strName;
13     }
14     void SetAge(int nAge)
15     {
16         age = nAge;
17     }
18 private:
19     int age;
20     string name;
21 };
22 int main()
23 {
24     Person p1;
25     p1.SetName("air");
26     p1.SetAge(18);
27 
28     //Person p2(p1);   错误的
29     return 0;
30 }

C++ 拷贝构造函数和赋值运算符

上面定义的类Person显式的删除了拷贝构造函数和赋值运算符,在需要调用拷贝构造函数或者赋值运算符的地方,会提示无法调用该函数,它是已删除的函数。

还有一点需要注意的是,拷贝构造函数必须以引用的方式传递参数,这是因为,在值传递给一个函数的时候,会调用拷贝构造函数生成函数的实参,如果拷贝构造函数的参数仍然是以值的方式,就会无限循环的调用下去,直到函数的栈溢出。

何时调用

拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象,但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而赋值运算符是将对象的值复制给一个已经存在的实例。这种区别从两者的名字也能轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生,如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。

调用拷贝构造函数主要有以下场景:

  1:对象作为函数的参数,以值传递的方式传给函数。

  2:对象作为函数的返回值,以值的方式从函数返回。

  3:使用一个对象给另一个对象初始化。

代码如下:

 1 #include <iostream>
 2 
 3 using namespace  std;
 4 class Person
 5 {
 6 public:
 7     Person() {}
 8     Person( const Person& p )
 9     {
10         cout << "Copy Constructor" << endl;
11     }
12 
13     Person& operator=( const Person& p )
14     {
15         cout << "Assign" << endl;
16         return *this;
17     }
18 
19 private:
20     int age;
21     string name;
22 };
23 
24 void f( Person p )
25 {
26     return;
27 }
28 
29 Person f1( )
30 {
31     Person p;
32     return p;
33 }
34 
35 
36 int main()
37 {
38     Person p;
39     Person p1 = p;    //  1 
40     Person p2;  //
41     p2 = p;           // 2
42     f(p2);            // 3
43 
44     p2 = f1();        // 4
45 
46     Person p3 = f1(); // 5
47 
48     return 0;
49 }

 C++ 拷贝构造函数和赋值运算符

1:虽然使用了“=”,但是实际上使用对象p来创建了一个新的对象p1.也就是产生了新的对象,所以调用的是拷贝构造函数。

2:首先声明了一个对象p2,然后使用复制运算符"=",将p的值赋值给p2,显然是调用了赋值运算符,为一个已经存在的对象赋值。

3:以值传递的方式将对象p2传入函数f内,调用拷贝构造函数构建一个函数f可用的实参

4:这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2.

5:应该是首先调用拷贝构造函数创建临时对象;然后再调用拷贝构造函数使用刚才创建的临时对象创建新的对象p3,也就是会调用两次拷贝构造函数。不过,编译器也没有那么傻,应该是直接调用拷贝构造函数使用返回值创建了对象p3。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java 复制Map对象(深拷贝与浅拷贝)
java复制Map对象(深拷贝与浅拷贝)CreationTime2018年6月4日10点00分Author:Marydon1.深拷贝与浅拷贝  浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
C++ 析构函数与内存池
CPrimer书中也提到编写class时要注意copycontrol成员(拷贝构造函数,赋值操作符,析构函数,C11又多个移动构造函数)。工作时在C和C之间切换,有时就忘记了C的细节(真的好讨厌)。C析构函数与构造函数对应,构造对象时调用构造函数,析构对象时调用析构函数,于是可以在对象的析构函数中释放资
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
C++11之右值引用(三):使用C++11编写string类以及“异常安全”的=运算符
前面两节,说明了右值引用和它的作用。下面通过一个string类的编写,来说明右值引用的使用。相对于C98,主要是多了移动构造函数和移动赋值运算符。先给出一个简要的声明:classString{public:String();String(constchars);
Wesley13 Wesley13
3年前
C++中构造函数和析构函数
构造函数定义它是一种特殊的方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。另外,一个类可以有多个构造函数,我们可以根据其参数个数的不同或参数类型的不同来区分它们(这就是构造函数的重载)特点1.构造函数的命名必须和类名完全相同;2.构造函数的功能主要用于在类的对象创建时定义
Wesley13 Wesley13
3年前
C++ 类与结构体 构造函数 详细相关理解整理
说到构造函数,通常是将讲对象创建时编译器自动调用构造函数为对象初始化,也可以说是分配内存空间。 学习了构造函数相对其中牵涉到的一些点作下大概的了解和学习,整理一下只是点。这里主要说下 类与结构体的差异/类与结构体包含继承关系时的构造调用/类的初始化列表/默认构造函数/拷贝构造函数以及牵涉到的相关内容结构体和类的区别
Wesley13 Wesley13
3年前
C++构造函数详解(复制构造函数 也是 拷贝构造函数)
构造函数是干什么的该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员。构造函数的种类!复制代码(https://oscimg.oschina.net/oscnet/54a3f729e89451abb86a0bec4639
Easter79 Easter79
3年前
Thinking in C++ Notes 拷贝构造函数
1.默认拷贝构造函数不会调用构造函数,而通过位拷贝来实现。2.可以使用多个构造函数,并使用默认参数。3.小心使用默认构造函数,当属性中有指针时,会造成多次析构而产生错误Reference:http://blog.csdn.net/lwbeyond/article/details/6202256(https://www.oschina