test类中隐藏的六个默认的函数
作用:对象所在的内存空间做初始化 、给对象赋资源
特点:
1.可以重载 :可以根据实际需要进行缺省的、多参重载
2.不依赖对象:对象无法调用构造函数,只能在对象定义点被调用
两者初始化的区别在于,初始化列表是真正意义上的初始化,它告诉编译器在实例化对象的时候以何种方式对成员赋值,而在前者的赋值规则写在了构造函数内部,是在已经生成了成员变量之后再进行的赋值操作。
初始化列表示例:
tips: 注意区分列表参数初始化和列表初始化的区别 。列表参数初始化即在函数的形参列表后通过fun(int ia) :mval(ia)
冒号+括号的这种方式初始化,而列表初始化一般是指如std::vector<int> vec{ 1,2,3,4,5 }; vec{1,2,3,4,5};
这种,在定义时通过 { } 括起来的列表初始化“数组”的行为。 事实上,在c++11标准中还有一种就地初始化的概念,这里先不做讨论。
对于 初始化列表 有几点特性需要注意:
比如以下操作,成员变量有引用类型和const类型,在c++中规定const类型为一个常量,定义时必须初始化,而引用我们认为是一个变量的别名也需要在定义时就初始化。所以以下操作只能使用初始化列表的方式初始化。
此外,如果有多个成员变量需要使用初始化列表的方式初始化,需要注意一点细节,初始化的顺序只与成员变量的定义顺序相关。
如以下程序,可以写成test(int a):ma(mb), mb(a){}
或test(int a):mb(a),ma(mb){}
因为成员变量的定义顺序为int mb; int ma;
,也就是说赋值顺序与初始化列表无关,只与成员变量被定义的顺序有关。
注:以下函数的test类成员均为int *ma
,表示数据成员为指针时,各成员函数的实现方法。
作用:释放对象所占的其他资源。
特点:
不可重载 : 对象销毁时会调用析构函数,并释放空间。依赖对象:可手动调用即this->~test()
或test t; t.~test()
,但是不建议,因为对象销毁时会自动调用,如果手动调用可能会引起内存空间的重复析构导致程序崩溃
作用:拿一个已存在的对象来生成相同类型的新对象
注意:类中提供的拷贝构造函数为一个浅拷贝类型,即如果成员变量中含有指针类型,它在进行拷贝构造的时候不会进行额外空间的开辟,最终会造成函数析构时的错误。
作用:拿一个已存在的对象给相同类型的已存在对象赋值
实现步骤
1.赋值判断
2.释放旧资源
3.生成新资源
4.赋值
6.常对象取地址函数
c++11以后增加了右值引用的概念,同时增加了移动构造函数、和移动赋值函数。
作用:针对某些情况构造对象的优化,避免重复的开辟内存。
使用场景:比如把临时对象的资源作为构建新对象的资源使用,而临时对象销毁时,资源继续被其他对象使用(这里就节省了一次旧对象资源的的销毁与新对象资源申请的开销)。
作用:资源的转移,针对某些情况下,节省内存的开辟。
另外一个关于移动构造的话题是异常。对于移动构造函数来说,国际警察日抛出异常有时是件危险的事情。因为可能移动语义还没完成,一个异常却抛出来了,这就会导致一些指针就成为悬挂指针。因此程序员应该尽量编写不抛出异常的移动构造函数,通过为其添加一个noexcept关键字,可以保证移动构造函数中抛出来的异常会直接调用terminate程序终止运行,而不是造成指针悬挂的状态。而标准库中,我们还可以用一个std::move_if_noexcept的模板函数替代move函数。该函数在类的移动构造函数没有noexcept关键字修饰时返回一个左值引用从而使变量可以使用拷贝语义,而在类的移动构造函数有noexcept关键字时,返回一个右值引用,从而使变量可以使用移动语义。
关于移动构造函数的示例程序,引用自《深入理解c++11》一书:
输出:左边是输出结果,右边是注释
一周的英文需要注意的是,在编译器中存在被称为rvo/nrvo的优化(rvo,return value optimization,返回值优化,或者n小沈阳资料rvo,named return value optimization)。因此在上述编译时使用了-fno-elide-constructors
选项在g++/clang++中关闭这个优化,这样可以使我们在代码运行的结果中较为容易地利用函数返回的临时量右值。
如果在编译的时候不使用该选项的话,我们写的很多含有移动语义的函数都被省略了。例如以下的代码
b 变量实际就使用了returnr天使的城value函数幼儿教具制作中a的地址,任何的拷贝和移动都没有了。通俗地说,就是b变量直接“霸占”了a变量。这是编译器中一个效果非常好的一个优化。不过rvo/nrvo并不是对任何情况都有效。比如有些情况下,一些构造是无法省略的。还有一些情况,即使rvo/nrvo完成了,也不能达到最好的效果。
总体而言,移动语义除了可以解决某些情况下编译器无法解决的优化问题,还在一些其他特殊的场合有着重要的用途(比如在unique_ptr中禁止构造函数,却可以通过移动的构造或移动赋值对unique_ptr拥有的资源进行转移)。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注www.887551.com的更多内容!
本文发布于:2023-04-06 01:57:53,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/aab4ee44874e651b601f5ba66eb26465.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:C++类中隐藏的几个默认函数你知道吗.doc
本文 PDF 下载地址:C++类中隐藏的几个默认函数你知道吗.pdf
留言与评论(共有 0 条评论) |