深入C++对象之构造函数语意学

来源:互联网 发布:淘宝店铺装修页尾 编辑:程序博客网 时间:2024/06/06 03:33

一:Default Constructor 的构建操作

    1.“带有Default Constructor”的Member Class Object

       如果一个类中包含一个class object 且这个class有default constructor 则编译器会生成一个default constructor  里面会对member data调用default constructor进行初始化。如果没有定义default constructor 而是定义了其他的带参构造函数,而里面又没有初始化class object ,则编译器会扩张此函数,将class object进行初始化。如果member object没有默认构造函数,且在此类的构造函数中没有初始化,则编译器会报错。

     2.“带有default constructor”的base class

      和上面的情况类似。

    3.“带有一个virtual function”的class

     编译器会为每一个派生类设定vptr初值,防止适当的virtual table 地址。对于class所定义的每一个constructor,编译器会安插一些码来做这样的事情。对于那些未声明任何constructor的class,编译器会给他们合成一个default constructor,以便正确的初始化每一个class object的vptr。

   4.“带有一个virtual base class”的class

     对于class所定义的每一个constructor,编译器会安插那些“允许每一个virtual base class 的执行期存取操作”的码。


注释:c++新手一般常见的误解(以下两个都是错的)

1.任何class如果没有定义default constructor,就会被合成一个来。

2.编译器合成出来的default constructor会明确设定“class内每个data member的默认值”。


二:Copy Constructor的构建操作

  有三种情况需要用到copy constructor :1.明确赋初值:word  x; word y = x;  2.做参数传递对象   3.返回一个对象

 bitwise and memberwist  copy

  在没有显示声明copy constructor 时,编译器可以通过简单的bitwise完成初始化操作,而不需要合成 copy constructor。

  memberwise 和bitwise copy:简单的将内建和派生的data member简单的从一个对象拷贝到另一个对象,而不会出错。 

  只有以下四种情况会合成copy constructor:

1.当class内含一个member object 而后者的class 声明有一个copy constructor时(不论是class设计者明确声明,或是被编译器合成);

2.当class 继承自一个class 而后者拥有copy constructor;

3.当class声明一个或多个virtual function;

4.当class派生自一个继承串链,其中有一个或多个virtual base classes;

   1,2较简单,3,4较复杂,因为需要对vptr和bptr保证正确性,如果需要切割的话就不能保证其正确性。

2.3程序转化语意学

1.明确初始化操作:

例:X x0;

  X x1=x0;

 X x2(x0);

X x3=X(x0);

以上代码会被转化为:

X x1;

X x2;

X x3;

X1.X::X(x0);

X2.X::X(x0);

X3.X::X(x0);

2.参数的初始化:

void foo(X x0);

//调用

X xx;

foo(xx);

//转化代码

X _temp0;

_temp0.X::X(xx);

foo(_temp0);

foo()的声明会被转换为:void  foo(X& x0);

3.返回值的初始化:

X bar(){

   X xx;

  //处理xx

  return xx;

}

void bar(X& _result){

  X xx;

  xx.X::X();

  _result.X::X(xx);


  return;

}

对此函数的调用:

X xx=bar;    //X xx;    bar(xx);

bar().memfunc();  // X _temp0;  (bar(_temp0),temp0).memfunc();

X (*pf)(); pf=bar;   // void (*pf)(X&); pf=bar;

4、使用者初始化(Optimization at the User Level)

在返回值初始化的编译器处理基础之上,用户自行定义一个“计算“的构造函数。具备抽象,但缺乏效率。

5、编译器初始化(Optimization at the Compiler Level)

 编译器的优化和返回值初始化的编译器处理方式一样。这样的优化方式叫做NRV(Named Return Value)。但是,不可或缺的是,我们需要一个拷贝构造函数,去开启编译器的优化。因此,在于是否一个类需要用户自己定义拷贝构造函数,这样的问题,需要如下解释:

例如:Class Point只包含了built-in的成员。那么,默认的拷贝构造函数则是trivial的。此时,我们无需去写一个显示的拷贝构造函数(explicit copy constructor),因为编译器会自动加上bitwise copy的行为,这里多此一举了。但是,如果class面临了很多以传值的方式做return value的时候,我们就需要去显示地提供一个拷贝构造,以开启编译器的NRV优化策略。


2.4成员初始化队伍

必须使用成员初始化列表的情况:

1.当初始化一个reference member ;

2.当初始化一个 const member;

3.当调用一个base class 的constructor ,而它拥有一组参数时;

4.当调用一个member class 的constructor,而它拥有一组参数时;

编译器会对初始化列表一一处理并可能重新排列,以反映出member的声明次序。它会安插一些代码到constructor体内,并置于任何explicit usercode之前。




    

0 0
原创粉丝点击