移动拷贝构造函数

1.什么是构造函数

“写在前面:文章中用的编译环境是windows下的vs 2019”

概念引入

有时在我们写代码的时候会忘记对数据进行初始化,在c++的类中,构造函数是一种特殊的成员函数,在每次创建创建一个类的时候会默认调用构造函数进行初始化工作。
构造函数用来完成一些必要的初始化工作,有了构造函数之后,就无需再单独写初始化函数,并且也不必担心忘记调用初始化函数,因为当你的代码中写了构造函数但是在创建对象的时候没有给构造函数传参编译器就会报错提示“类XXXX不存在默然构造函数”。

概念

1.名字与类名相同,可以有参数,但是不能有返回值(void也不行)
2.作用是对对象进行初始化工作,如给成员变量赋值等。
3.如果定义类时没有写构造函数,系统会生成一个默认的无参构造函数,默认构造函数没有参数,不做任何工作。
4.如果定义了构造函数,系统不再生成默认的无参构造函数
5.对象生成时构造函数自动调用,对象一旦生成,不能在其上再次执行构造函数
6.一个类也可以有多个构造函数,为重载关系

例子

#include<iostream>
using namespace std;class Myclass
{public:Myclass(int num){m_num = num;}int getNum(){return m_num;}
private:int m_num;
};int main()
{Myclass class1(100);cout<<class1.getNum();return 0;
}

上述例子定义了一个Myclass()构造函数来设置m_num的值,这样在每次定义对象的时候都必须初始化,解决了用户在写代码的时候忘记初始化的情况。

2.拷贝构造函数

首先对于普通类型的对象来说,它们之间的复制是很简单的,例如:

int a = 100;
int b = a;

而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。
下面看一个类对象拷贝的简单例子。

#include<iostream>
using namespace std;class Myclass
{public:Myclass(int num){m_num = num;}int getNum(){return m_num;}
private:int m_num;
};int main()
{Myclass class1(100);Myclass class2(class1);cout << class1.getNum() << endl;cout << class2.getNum()<< endl;return 0;
}

可以看到他打印了两次100,系统为对象class2分配了内存并完成了与对象class1的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。

3.默认构造函数

如果用户没有定义构造函数,那么编译器会给类提供一个默认的构造函数,但是只要用户自定义了任意一个构造函数,那么编译器就不会提供默认的构造函数。
每一次定义对象系统都会默认的生成一个无参的默认构造函数,如下。

class Myclass
{public:Myclass()//系统会默认生成一个不带参数的构造函数{cout<<"hello world"<<endl;}
};
int main()
{Myclass class;
}

在定义对象的时候,系统会自动生成一个无带参数的构造函数但是这里我显示的写出来了,此时运行代码输出 hello world 证明在定义对象的时候确实调用了无参的构造函数,其实不写出来他也会隐式的调用一个无参的构造函数,但是他什么都不干。

那如果不想编译器自动的生成一个无参的构造函数或想要编译器使用自动生成的无参构造函数呢?

c++11引入了两个关键字:delete和default 关键字

Myclass() = default;//使用系统默认的构造函数
Myclass() = delete;//禁止使用默认构造函数和拷贝构造函数

4.移动拷贝构造函数

1.我们用对象class1初始化对象class2,对象class1我们就不在再使用,但是对象class1的空间还在(在析构之前),拷贝构造函数,就是把class1对象的内容复制一份到class2中,那么为什么我们不能直接使用class1属性所指向的空间,然后释放的时候只释放class1的空间并把他指向的那块空间的控制权交给class2,这样就避免了新的空间的分配,大大降低了构造的成本。这就是移动构造函数设计的初衷。
2.拷贝构造函数中,对于指针,我们一定要采用深拷贝,而移动构造函数中,对于指针,我们采用浅拷贝。浅拷贝之所以危险,是因为两个指针共同指向一片内存空间,若第一个指针将其释放,另一个指针的指向就不合法了,两次释放同一块地址就会产生异常。
3.移动构造函数的参数和拷贝构造函数不同,拷贝构造函数的参数是一个左值引用,但是移动构造函数的初值是一个右值引用。意味着,移动构造函数的参数是一个右值或者将亡值的引用。也就是说,只用用一个右值,或者将亡值初始化另一个对象的时候,才会调用移动构造函数。而move语句,就是将一个左值变成一个将亡值。

接下来用一个例子来展示。

#include<iostream>
using namespace std;class student
{public:student(const char* name){cout << "contructor student" << endl;int len = strlen(name);m_name = new char[len + 1];strcpy_s(m_name, len + 1, name);}//拷贝构造函数student(const student& other){cout << "contructor copy student"<<endl;//this->m_name = other.m_name;//浅拷贝,没有分配内存空间两次析构析构的是同一块空间就会有问题int len = strlen(other.m_name);m_name = new char[len + 1];strcpy_s(this->m_name, len + 1, other.m_name);//深拷贝,分配内存空间 }//移动拷贝构造函数student(student&& other){cout << "move contructor cpy student" << endl;this->m_name = other.m_name;cout << m_name << endl;other.m_name = nullptr;}student(){m_name = nullptr;}private:char * m_name;
};int main()
{student stu("zhangsan");//拷贝构造函数student stu3 = stu;//拷贝student sut1(std::move(stu));//移动拷贝构造函数return 0;
}

调试运行:

可以看到创建对象的时候调用了构造函数给m_name赋值并输出输出contructor student
student stu3 = stu调用了拷贝函数并采用深拷贝给m_name赋值并输出conctruct copy student
student stu1(std::move(stu))将左值引用改成右值引用并输出“zhangsan”。发生对象移动的前提是要移动的对象之后不再用了,这时就不会调用拷贝构造函数移交控制权给新的对象不发生值的拷贝。

C++移动拷贝构造函数相关推荐

  1. C++ 复制构造函数或者拷贝构造函数

    复制构造函数 是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象. 复制构造函数通常用于: 通过使用另一个同类型的对象来初始化新创建的对象. 复制对象把它作为参数传 ...

  2. C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)

    1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...

  3. 【C++】何时需要自定义拷贝构造函数和赋值符

    先来说结论:当类中有指针类型成员变量的时候,一定要自定义拷贝构造和赋值运算符 原因:当我们在有指针类成员变量的时候,还是用默认拷贝构造函数(拷贝构造函数执行的时候会调用赋值符),默认赋值为浅拷贝,会导 ...

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

    文章目录 拷贝构造函数 重载赋值运算符 赋值运算符和拷贝构造函数最大区别是赋值运算符没有新的对象生成,而拷贝构造函数会生成新的对象. 为了更加形象 准确得描述 赋值运算符和拷贝构造函数得区别,将详细通 ...

  5. 函数返回类的对象与拷贝构造函数

    C++中,如果我们在一个函数中,定义了一个类的对象,然后返回这个对象,在main函数中用一个对象去接受这个返回的对象的时候,这里面参与的函数调用大家可能不熟悉,这里通过程序和注释的方式给大家讲解一下. ...

  6. 拷贝构造函数和赋值函数的一些知识

    /*******************拷贝构造函数和赋值运算符重载有以下两个不同之处***************************/ 1.拷贝构造函数生成新的类对象,而赋值运算符不能. 2. ...

  7. display函数怎么使用_Chapter19:拷贝构造函数

    对于计算机来说,拷贝是指用一份原有的.已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据.在 C++中,拷贝并没有脱离它本来的含义,只是将这个含义进行了"特化",是指 ...

  8. C++复制控制:拷贝构造函数

    一.拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.与默认构造函数一样 ,拷贝构造函数可由编译器隐式调用.拷贝构造函数应用的场合为: (1)根据另一个同类 ...

  9. 复制构造函数(拷贝构造函数)

    也许很多C++的初学者都知道什么是构造函数,但是对复制构造函数(copy constructor)却还很陌生.对于我来说,在写代码的时候能用得上复制构造函数的机会并不多,不过这并不说明复制构造函数没什 ...

  10. 不存在从void转换到sqlist的适当构造函数_拷贝构造函数与赋值构造函数

    拷贝构造函数与赋值构造函数 在C++中,如果要创建一个新的类,并用已有的类来给它附初值.就要用到拷贝构造函数,拷贝构造函数又分为两种. 1.合成的拷贝构造函数 在你没有定义自己的拷贝构造函数而又调用了 ...

最新文章

  1. 如何让ie 7 支持box-shadow
  2. Redis 安装详细过程(redis基本使用(服务端和客户端)、修改密码)
  3. Python进阶-----类、对象的相关知识
  4. “进度条”博客——第四周
  5. debian下面的apt-fast安装
  6. VTK:一个面向对象的可视化类库(zz)
  7. (新聞) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球
  8. 22 为特性 采购申请凭证类型 解决第一个矛盾
  9. 常见的6种MySQL约束
  10. 在未来人类在计算机行业中扮演什么角色,刘慈欣:未来人类可能生活在计算机里...
  11. IDEA商店无法打开的解决方法
  12. 基于Microsoft Translator API的vim翻译插件
  13. sata AHCI驱动下载(AMD Intel Nvidia)
  14. 《人月神话》读后感与读书笔记
  15. C. The Intriguing Obsession
  16. 前端html——图片插入
  17. Visual Studio 2019 Community 许可证过期解决方法
  18. 计算机与代数---如何计算sqrt---方法和实现
  19. chmod 777 修改文件权限
  20. MySQL编程实战三之求任务执行批次号

热门文章

  1. 玉流馆,吃狗肉看朝鲜MM
  2. 斗图还要上微博找资源?微信小程序表情包了解一下
  3. Hexo博客搭建之配置文件详解(Melody)
  4. Mac搭建PHP环境
  5. EaselJs 测试小结
  6. 计算机实训活动简讯,院内动态 | 我院计算机专业开展校内实训活动
  7. 进入到win7安装界面后鼠标键盘无法使用
  8. java日期减天数_使用Java中的Calendar.DATE从当前日期减去天数
  9. 蔚来汽车哭诉没钱赚,大宗商品成本上升,下调第二季度营收预测,
  10. 驱动安装不上的终极办法