2.3 程序转化语意学

来源:互联网 发布:淘宝会员号 编辑:程序博客网 时间:2024/06/16 16:24

一、显式的初始化操作

X x0;void foo_bar(){    X x1(x0);    X x2 = x0;    X x3 = X(x0);}

二、参数的初始化

把一个class object当做参数传给一个函数(或者作为一个函数的返回值),相当于以下操作:

X  xx = arg;

其中,xx代表形式参数或返回值,arg为真正的参数值(即实参)。

下面这样的调用方式:

// 已知foo函数的声明void foo(X x0);X xx;// ...foo(xx);

将转换为:

// C++伪码// 编译器产生的临时对象X __temp0;// 编译器调用copy constructor__temp0.X::X(xx);// 重新改写函数的调用操作,以便使用上述临时对象foo(__temp0);

三、返回值的初始化

已知如下的函数定义:

X bar(){    X xx;    // ... 处理xx    return xx;}

bar()的返回值如何从局部对象xx中拷贝过来?Stroustrup在cfront中的解决方法是一个双阶段优化:
1、首先加入一个额外参数,类型是class object的一个reference。该参数用来存放“拷贝构建”而得的返回值。
2、在return指令之前安插一个copy constructor调用操作,以便将欲传回object的内容当做上述新增参数的初值。
3、函数的返回值为return,不返回任何值

有了这样的算法,bar()转化如下:

// C++伪码void bar(X &__result){    X xx;    // bar()函数调用时,编译器调用X的default constructor    xx.X::X();    // 编译器调用copy constructor    __result.X::X(xx);    return;     }

练习一下:
1、X xx = bar(); 转换为

// 不必施行default constructor ???X xx; bar(xx);

2、bar().memfunc();可能被转化为:

// 编译器产生临时对象X __temp0;(bar(__temp0), __temp0).memfunc();

3、已知程序声明了一个函数指针:X ( *pf )(); pf = bar;,将被转化为:

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

四、Copy Constructor:要还是不要?

考虑下面的类Point3d:

class Point3d{public:    Point3d(float x, float y, float z);    // ...private:    float _x, _y, _z;};

这个类的设计者应该提供一个explicit copy constructor吗?不需要,因为该类既没有任何member(或base)class objects带有copy constructor,也没有任何的virtual base class或virtual function。所以,默认情况下,一个Point3d class object的“memberwise”初始化操作将导致“bitwise copy”(博主注:其实它们是一样的)。这样的效率很高,也很安全。因为数据成员是以数值存储的。bitwise copy既不会导致memory leak,也不会产生address aliasing,因此,既快速,又安全。

那么,该类的设计者到底应该提供一个explicit copy constructor吗?很明显不要。但如果被问及是否预见class需要大量的memberwise初始化操作,例如以传值的方式返回objects?如果回答是yes,那么提供一个copy constructor的explicit inline函数实例就非常合理——在你的编译器提供NVR的前提下。


参考文献:《深度探索C++对象模型》侯捷 译

0 0
原创粉丝点击