艺考网
全国站

现代C++ 移动构造、移动赋值、复制构造、复制赋值

xunaa
2024-10-07 06:58:43
编辑说
c++primer中说:构造函数是一种特殊的成员函数。只要创建了类类型的新对象,就必须执行构造函数。构造函数的工作是确保每个对象的数据成员都有适当的初始值。
构造函数与其他函

c++primer中说:构造函数是一种特殊的成员函数。只要创建了类类型的新对象,就必须执行构造函数。构造函数的工作是确保每个对象的数据成员都有适当的初始值。

构造函数与其他函数不同:它们与类具有相同的名称,并且没有返回类型。

构造函数与其他函数相同:构造函数也有一个形式参数列表(可以为void)和一个函数体。 (参数列表为void的构造函数为默认构造函数)

构造函数构造类对象的顺序是: 1. 内存分配。当调用构造函数时,hermit\display 会初始化每个数据。

2.执行构造函数的执行。

1.构造函数初始化表

A() :a(0){}我们使用构造函数初始化来初始化数据成员。但是,在不使用初始化表的构造函数中,数据成员在构造函数主体中分配。

当我们编写一个类时,必须在构造函数初始化表中初始化一些成员。 (没有默认构造函数、const 或引用类型成员的类类型成员)

编写代码时请注意,可以初始化const对象或引用类型对象,但不能给它们赋值。也就是说,初始化工作需要在我们执行构造函数体之前完成,所以唯一的机会就是初始化表。从这一点可以看出,初始化表是在函数体之前执行的。

在初始化表中,成员初始化的顺序不是您编写初始化表的顺序,而是定义成员的顺序。

当初始化类类型的成员时,初始化列表指定实际参数并将它们传递给成员类型的构造函数。

c++primer中有一个书店的例子:

Sales-item(): isbn(10, '9'),units_sold(0),revenue(0.0) {}什么时候必须使用我们的初始化表?

当存在一个类成员,其本身是一个结构体或类,并且只有一个带参数的构造函数(没有默认构造函数)时。这时,如果我们想要初始化该成员,就需要调用该成员的构造函数。这个时候,我们就需要我们的初始化表,如果不使用初始化表的话,内存分配就会出现问题。

初始化列表的优点:主要针对自定义类型,初始化列表作用在函数体之前,它调用构造函数来初始化对象。

但在函数体内,需要先调用构造函数,然后再赋值,效率不如初始化表。

2.默认参数构造函数

A(int i=1) :a(i), ca(i), ra(i){}3.默认构造函数

现代C++ 移动构造、移动赋值、复制构造、复制赋值

合成默认构造函数:当类中没有定义构造函数时(注意是构造函数),编译器自动生成一个函数。

但我们不能过于依赖编译器。如果我们的类有复合类型或自定义类型成员,我们需要自己定义构造函数。

自定义默认构造函数:

A(): a(0) {}A(int i=1): a(i) {}问题可能是第二个构造函数是否也是默认构造函数?是的,因为参数中有默认值。

如果我们看一张图,就一目了然了:

4.类型转换

在C++primer中,书店问题的一个例子是,在将字符串对象或者iostream对象传入参数时,会发生隐式转换,从而产生问题。

C++11 中添加的新功能!

在我的上一篇博客中,我添加了一张图片来具体了解移动构造函数是如何工作的。

至此,我们已经窃取了临时变量的内存空间,并为自己所用。节省开辟空间的时间。

A(A h) : a(h.a){ h.a=nullptr; //还记得nullptr吗? }正如你所看到的,这个构造函数的参数是不同的,并且有两个运算符。移动构造函数接收“右值引用”参数。

我还要说一下,这里h.a 设置为空。如果不是,ha 将在移动构造函数末尾执行析构函数时破坏我们窃取的内存。 h.a 将成为悬空指针。

移动构造函数何时触发?这是一个临时对象(右值)。使用临时对象时执行移动语义。

这里需要注意的是,当发生异常时,尽量保证移动构造函数中不发生异常。可以使用noexcept关键字来保证move构造函数中抛出的异常会直接调用terminate终止程序。

右值参考:

在上一篇博客中,我们提到了垂死值,它是C++11 中与右值引用相关的新表达式。

在C++11 中,右值引用是引用右值的类型。右值通常没有名称,所以我们只能通过引用来发现它的存在。

比较以下两种说法:

现代C++ 移动构造、移动赋值、复制构造、复制赋值

T a=returna();T b=returnb();此时a是右值引用,比b少一次对象销毁和对象构造过程。 a直接绑定returna返回的临时变量。 b 只是由临时变量值构造而成。

你应该能够看得清楚。右值引用是赋予返回的右值(临时对象)新的生命,延长其生命周期。临时对象被销毁,但右值引用仍然存在。

但需要注意的是,右值引用不能绑定左值:int a; int c=a;这是行不通的。

这里的一个函数是move 函数,它可以将左值强制转换为右值引用。

3. 移动赋值运算符

其原理与移动构造函数相同,这里不再赘述。

1. 一个类有一个或多个作为指针的数据成员。

2.构造函数中还有代表分配的其他资源的成员。其他类在创建新对象时必须做一些特定的工作。

5. 赋值运算符

与构造函数一样,可以通过指定不同类型的右操作数来重载赋值运算符。

下面是赋值运算符的写法:

A 运算符=(const A h){assert(this !=h);this-a=h.a;return *this;} 6. 析构函数

作为构造函数的补充,当对象超出范围或动态分配的对象被删除时,析构函数会自动应用。析构函数可用于释放在构造对象时获取的资源或在对象的生命周期内获取的资源。无论类是否定义了自己的析构函数,编译器都会自动执行类中非静态数据成员的析构函数。

析构函数的操作:

当对象引用或指针越界时,析构函数不会被执行。仅当指向动态分配对象的指针被删除或实际对象超出范围时,才会调用析构函数。

综合析构函数:

编译器总是合成一个析构函数,以与创建对象相反的顺序销毁每个非静态成员。请注意,合成析构函数不会删除指针成员指向的对象。

用户评论

雨后彩虹

刚开始学习cpp的时候感觉这几个概念太复杂了,现在理解多了点

    有19位网友表示赞同!

﹏櫻之舞﹏

经常要用到这些,对程序效率提升帮助很大!

    有13位网友表示赞同!

墨染殇雪

移动和拷贝之间的区别还是很容易混淆的,需要多练习一下

    有8位网友表示赞同!

金橙橙。-

这段时间在学习C++的内存管理,感觉了解了这些概念就能解决很多问题

    有7位网友表示赞同!

寒山远黛

现代C++真是越来越棒了,效率超高!

    有13位网友表示赞同!

浮世繁华

移动构造函数跟拷贝构造函数的区别就是不分配新的内存哦

    有5位网友表示赞同!

有一种中毒叫上瘾成咆哮i

学懂了这些就离高级编程越来越近了

    有11位网友表示赞同!

哽咽

感觉学习现代C++比旧版本更轻松,概念更清晰简洁

    有16位网友表示赞同!

╯念抹浅笑

学习的时候最好跟着代码实践,更容易理解

    有11位网友表示赞同!

巷口酒肆

移动赋值和拷贝赋值都需要注意指针的变化,很容易掉入坑里去呢!

    有5位网友表示赞同!

失心疯i

看代码的时候经常会看到这些函数的身影,这下终于明白了!

    有11位网友表示赞同!

夜晟洛

现代C++的内存管理真是太棒了!学习起来有些挑战,但很有收获!

    有9位网友表示赞同!

醉婉笙歌

理解移动和拷贝的关键就在于资源的 Ownership(所有权), 很容易被误解,需要反复练习

    有11位网友表示赞同!

见朕骑妓的时刻

学习C++真是个挑战不断的过程!但每一次理解都会让我觉得非常成就感满满

    有10位网友表示赞同!

拽年很骚

感觉现在很多教材都把现代C++这些概念讲解得很清晰了

    有5位网友表示赞同!

浅巷°

移动操作比拷贝操作效率更高, 对于处理大对象特别有优势

    有18位网友表示赞同!

敬情

这些概念都是编程里必须要掌握的,对理解底层机制非常重要!

    有10位网友表示赞同!

免责声明
本站所有收录的学校、专业及发布的图片、内容,均收集整理自互联网,仅用于信息展示,不作为择校或选择专业的建议,若有侵权请联系删除!

大家都在看

现代C++ 移动构造、移动赋值、复制构造、复制赋值

现代C++ 移动构造、移动赋值、复制构造、复制赋值

c++primer中说:构造函数是一种特殊的成员函数。只要创建了类类型的新对象,就必须执行构造函数。构造函数的工作是确保每个对象的数据成员都有适当的初始值。 构造函数与其他函
2024-10-07
一篇文章了解常用Linux shell 命令的4 种使用方法

一篇文章了解常用Linux shell 命令的4 种使用方法

read命令 读取:的基本格式 读取[-rs] [-a ARRAY] [-d delim] [-n nchars] [-N nchars] [-p 提示符] [-t 超时] [var1 var2 var3.] -n(无换行符) -p(提示语句) -n(字符数) -t(
2024-10-07
String.valueOf(Object) 与String.valueOf(Object) 的比较对象.toString(对象)

String.valueOf(Object) 与String.valueOf(Object) 的比较对象.toString(对象)

String.valueOf(Object) 和Objects.toString(Object) 这两个方法本质上做同样的事情: 对传入的对象调用toString() 方法。在这种情况下,只要字符串“null”不为null,或者将null
2024-10-07
精通英语:直到

精通英语:直到

2.他们工作到八点钟。 3.她昨晚十点才睡觉。昨晚她直到十点才睡觉。 4.直到听到闹钟声我才醒来。 (点击) 直到它的同义词是直到。 作为准备。随后是n./n.phr。它的意思是直到
2024-10-07
初中英语考试70要求句型详解:till/until和not

初中英语考试70要求句型详解:till/until和not

4. not.until.句型中的强调句,无需倒置词序。 他发明了许多治疗伤员的新方法,但直到战后他才做出了最重要的发现。 5. not.until.句型与其他句型的比较 not.until. 句型总是表
2024-10-07
在强调句中使用not.until. 结构

在强调句中使用not.until. 结构

大家一定要熟悉强调句的使用,尤其是作为形式主语的强调句型。但当句子中出现not.until.时,很多朋友还是会感到困惑。今天我就和大家一起探讨一下not…until…强调句的用法。
2024-10-07
直到和不.直到的用法总结

直到和不.直到的用法总结

til的意思是“直到”,表示动作持续到某一时间点,常与进行性动词连用; not.until 的意思是“直到.”,表示该动作要到某个时间点才会发生,否则不会发生。它经常与瞬态动词一起使用
2024-10-07
英语not.until用于强调句型的用法

英语not.until用于强调句型的用法

not.until 用于强调句型的用法 英语语法和句法重点句子 有这么一道测试题,涉及到not…until…句型: 他摘下墨镜并不是__________,我意识到他是一位著名歌手。 A. 当,那个B. 直
2024-10-07
热词的使用不仅……而且……

热词的使用不仅……而且……

1.就近原则不仅……而且连接两个主语时,谓语动词必须与最近的主语保持相同的人称和数字。也就是说,句子中的谓语动词既由其后的单词决定,又由谓语的单复数形式决定。 不仅他的
2024-10-07
不仅……而且……

不仅……而且……

“不仅……而且……”: 1.他不仅来了,还带来了礼物。他不仅来了,还带来了一份礼物。 2.她不仅唱歌好听,而且跳舞也很漂亮。她不仅唱歌好听,而且跳舞也很漂亮。 3.他们不仅聪明,而
2024-10-07