程序转化语义学(Program Transform Semantics)
显式的初始化操作
已知有这样的定义:
X x0;
下面的三个定义每一个都明显地以x0来初始化其class object:
void foo_bar(){
X x1(x0);
X x2 = x0;
X x3 = X(x0);
}
必要的程序转化有两个阶段:
1.重写每一个定义,其中的初始化操作会被剥除。(在严谨的C++用词中,“定义”是指“占用内存的行为)
2. class的copy constructor调用操作会被安插进去
上面的例子转化之后称为这样子:
void foo_bar() { X x1; X x2; X x3; //编译器安插 X copy consruction的调用操作 x1.X::X(x0); x2.X::X(x0); x3.X::X(x0); }
其中的:
x1.x::X(x0);
就表现出对以下的copy constructor的调用:
x::X(constructor X& xx);
参数初始化:
C++标准中说,把一个class object当作参数传给一个函数(或当作一个函数的返回值),相当于以下形式的初始化操作:
X xx = arg;
其中xx代表形式参数(或返回值)而arg代表真正的参数值。因此这个函数:
void foo(X x0);
下面的调用方式:
X xx;
foo(xx);
被转化为:
//编译器产生出来的临时对象 X _temp0; //编译器对copy constructor的调用 _temp0.X::X(xx); //重新改写函数调用操作,以便试用上述的临时对象 foo(_temp0); //临时性object以class X的copy constructor正确地设定了初值,然后再以bitwise方式拷贝到x0,这个局部实例中,所以foo()的声明也必须被转化 void foo(X& x0);
其中class X声明了一个destructor,它会在foo()函数完成之后被调用,对付那个临时性的object。
返回值的初始化:
已知下面这个函数定义:
X bar() { X xx; return xx; }
编译器将会执行一个双阶段转化:
1. 首先加上一个额外参数,类型是class object的一个reference。这个参数将用来放置被拷贝构建(copy constructed)而得的返回值。
2. 在return指令之前安插一个copy constructor调用操作,以便将欲传回给object的内容当作上述新增参数的初值。
根据这样的算法,bar()转换如下:
//函数转换 //以反映出copy constructor的应用 void bar(X &_result) //加上一个额外参数 { X xx; //编译器所产生的default constructor调用操作 xx.X::X() //...处理xx //编译器所产生的copy constructor调用操作 _result.X::XX(xx); return; }
现在编译器必须转换为每一个bar()调用操作,以反映其新定义。例如:
X xx = bar()
将被转化为下列两个指令:
//注意,不必施行default constructor X xx; bar(xx);