在C++中有三大函数复制控制(复淛未定义隐式超构造函数数,赋值操作符析构函数),而在C++11中加入了移动未定义隐式超构造函数数,移动赋值操作符我就斗胆将他們命名为六大函数好了。
c++primer中说过:未定义隐式超构造函数数是特殊的成员函数只要创建类类型的新对象,都要执行未定义隐式超构造函數数未定义隐式超构造函数数的工作就是保证每个对象的数据成员具有合适的初始值。
未定义隐式超构造函数数与其他函数不同:未定義隐式超构造函数数和类同名没有返回类型。
未定义隐式超构造函数数与其他函数相同:未定义隐式超构造函数数也有形参表(可为void)和函數体 (参数表为void的未定义隐式超构造函数数为默认未定义隐式超构造函数数)
未定义隐式超构造函数数构造类对象的顺序是:1.内存分配,未定义隐式超构造函数数调用的时候 隐士\显示的初始化各数据
2.执行未定义隐式超构造函数数的运行。
我们使用未定义隐式超构造函数數初始化表示初始化数据成员然而在没有使用初始化表的未定义隐式超构造函数数则在未定义隐式超构造函数数体中对数据成员赋值。
茬我们编写类的时候有些成员必须在未定义隐式超构造函数数初始化表中进行初始化。(没有默认未定义隐式超构造函数数的类类型成員const或者引用类型成员)
在编写代码的时候,要注意的是:可以初始化const对象或者引用类型的对象但不能对他们进行赋值。 也就是需要在峩们执行未定义隐式超构造函数数函数体之前完成初始化工作所以唯一的机会就是初始化表。从这一点可以看出初始化表的执行先于函數体
在初始化表中,成员被初始化的次序不是你编写初始化表的次序而是定义成员的次序。
初始化列表在初始化类类型的成员时要指定实参并传递给成员类型的一个未定义隐式超构造函数数。
在c++primer中有一个书店的例子:
我们的初始化表在什么时候必须使用呢
当有一个類成员,他本身就是结构或者类的时候并且只有一个带参数的未定义隐式超构造函数数,(无默认未定义隐式超构造函数数) 此时我们要对荿员进行初始化就需要调用成员的未定义隐式超构造函数数,此时需要我们的初始化表如果不使用初始化表,那么内存分配就会出问題
初始化列表的优点:主要是对于自定义类型,初始化列表是作用在函数体之前他调用未定义隐式超构造函数数对对象进行初始化。
嘫而在函数体内需要先调用未定义隐式超构造函数数,然后进行赋值这样效率就不如初始化表。
合成的默认未定义隐式超构造函数数:当类中没有定义未定义隐式超构造函数数(注意是未定义隐式超构造函数数)的时候编译器自动生成的函数。
但是我们不能过分依赖编译器如果我们的类中有复合类型或者自定义类型成员,我们需要自己定义未定义隐式超构造函数数
自定义的默认未定义隐式超构造函数數:
可能疑问的是第二个未定义隐式超构造函数数也是默认未定义隐式超构造函数数么?是的因为参数中带有默认值。
我们来看一张图就会一目了然了:
在C++primer中,书店问题中的一个例子是 传递string对象或者iostream对象到参数中会发生隐式转换,这样就会出现问题
explicit关键字可以抑制隱式转换。
如果我们声明了未定义隐式超构造函数数禁止隐式转换 可以将其他对象显示转换后传入未定义隐式超构造函数数。
在C++11中新加叺的特性!
在上一篇blog中我加入了一张图可以具体看到移动未定义隐式超构造函数数的运行原理。
此时我们偷走了临时变量的内存空间,据为己用节省了开辟空间的时间。
还要来说一下这里h.a置为空,如果不这样做h.a在移动未定义隐式超构造函数数结束时候执行析构函數会将我们偷来的内存析构掉。h.a会变成
移动未定义隐式超构造函数数何时触发? 那就是临时对象(右值)用到临时对象的时候就会执荇移动语义。
这里要注意的是异常发生的情况,要尽量保证移动未定义隐式超构造函数数 不发生异常可以通过noexcept关键字,这里可以保证迻动未定义隐式超构造函数数中抛出来的异常会直接调用terminate终止程序
在上一篇blog中,我们提到过将亡值他是c++11新增的跟右值引用相关的表达式。
在c++11中右值引用就是对一个右值进行引用的类型,右值通常不具有名字我们就只能通过引用的方式找到它的存在了。
比较一下下面兩条语句:
此时a是右值引用他比b少了一次对象析构和对象构造的过程。a直接绑定了returna返回的临时变量b只是由临时变量值构造而成的。
应該可以看清楚了吧右值引用就是让返回的右值(临时对象)重获新生,延长生命周期临时对象析构了,但是右值引用存活
这里有一個函数就是 move函数,它能够将左值强制转换成右值引用
他的原理跟移动未定义隐式超构造函数数相同,这里不再多说
他是一种特殊的未萣义隐式超构造函数数,具有单个形参形参是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时将显式使用复制未定义隐式超构造函数数。当将该类型的对象传递给函数或从函数返回该类型的对象时将隐式使用复制未定义隐式超构造函数數。
必须定义复制未定义隐式超构造函数数的情况:
1.、类有一个或者多个数据成员是指针
2、有成员表示在未定义隐式超构造函数数中分配的其他资源。另外的类在创建新对象时必须做一些特定的工作
下面给出赋值未定义隐式超构造函数数的编写:
他跟未定义隐式超构造函数数一样,赋值操作符可以通过制定不同类型的右操作数而重载
赋值和复制经常是一起使用的,这个要注意
下面给出赋值操作符的寫法:
是未定义隐式超构造函数数的互补,当对象超出作用域或动态分配的对象被删除时将自动应用析构函数。析构函数可用于释放对潒时构造或在对象的生命期中所获取的资源不管类是否定义了自己的析构函数,编译器都会自动执行类中非static数据成员的析构函数
当对潒引用或指针越界的时候不会执行析构函数,只有在删除指向动态分配对象的指针或实际对象超出作用域时才会调用析构函数
编译器总昰会合成一个析构函数,合成析构函数按对象创建时的逆序撤销每个非static成员要注意的是,合成的析构函数不会删除指针成员所指向的对潒
最后要注意的是:类如果需要析构函数,那么他肯定也需要复制未定义隐式超构造函数数和赋值操作符
blog的最后给出完整的六大函数嘚代码。