2.3 program transformation semantics 程序转化语义学
显式初始化操作
显式调用 copy constructor
参数初始化
X xparam = xarg;
void foo(X x0) // 函数原型
X xx;
foo(xx); // 调用函数
宏观上,局部实例x0通过memberwise方式将xx当作初值
// **************************** 编译器实现***********************************
X _temp; // 编译器产生临时对象
_temp.X::X(xx); // copy constructor
foo(_temp); //重新改写函数调用操作。以便使用上述临时对象
// **************************************************************************
// 临时对象通过copy constructor设定初值,再以 bitwise 拷贝到x0这个局部实例中。
此时foo()声明也发生了改变,形参变成了引用
void foo(X& x0)
返回值初始化
X Bar()
{
X xx;
return xx;
}
Ⅰ、添加一个额外参数,类型是class object reference。该参数用来存放返回的值。
Ⅱ、return之前执行copy constructor操作,将要传回的值拷贝给上述引用对象。
//可能的代码
void Bar(X &__result) //额外的参数
{
X xx; //剥离
xx.X::X() //default constructor
__result.X::X(xx); //编译器产生的 copy constructor 操作
return;
}
所以对于 Bar():
//看到的
X xx = Bar();
//可能实际的代码
X xx; // 这里不用执行default constructor,因为之后仅仅用来拷贝存储返回数据的。
Bar(xx);
//看到的
Bar().MemberFunc() //MemberFunc() 为 class X 的 member function
//可能实际上的代码
X __temp0; //编译器会产生一个临时 object
(Bar(__temp0), __temp0).MemberFunc(); // Bar(__temp0); __temp0.MemberFunc();
// **************************如果程序声明了一个函数指针******************************
//看到的
X (*pf)();
pf = Bar; //pf 为 函数指针
//可能实际的代码
X (*pf)(X&) //实际此函数指针与该函数的真面目相同
pf = Bar;
Optimization at the User Level (在用户层面做优化)
X bar(const T &y, const T &z)
{
X xx;
//......以y、z处理xx
return xx;
}
// 按照上述思路应该是这样的:
void bar(X& _result, const T &y, const T &z)
{
X xx;
//......以y、z处理xx
__result.X::X(xx);
return;
}
// 事实上是这样的:
X bar(const T &y, const T &z)
{
return X(y, z);
}
// 被转化成执行:
void bar(X& _result)
{
_result.X::X(y,z);
return;
}
// 好处:_result直接计算出来,避免了copy constructor 拷贝,效率高!
Optimization at the Compiler Level (在编译器层面做优化)
像bar()这样的函数,所有的return指令传回相同的具名数值(named value),因此编译器有可能自己做优化,方法是以result参数取代named return value。例如 bar():
X bar()
{
X xx;
//...处理xx
return xx;
}
用 _result 替代 xx:称为 Named Return Value(NRV)优化
void bar(X& __result)
{
__result.X::X(); // 调用 default constructor
//...直接处理__result
return;
}
eg:
class X
{
friend X foo(double);
public:
X(){ memset( array, 0, 100*sizeof(double) ); }
private:
double array[100];
};
X foo(double val)
{
X local;
local.array[0] = val;
local.array[100] = val;
return local;
}
调用 foo() 1000 万次,每次都产生一个 X 对象,设置每个对象的成员数组#0和#99有初值
int main()
{
for(int cnt = 0; cnt < 10000000; cnt++){ X t = foo(double(cnt)); }
return 0;
}
由于缺少 copy constructor,无法进行 NRV 优化。在类中加上拷贝构造函数:
拷贝构造函数: 类名(类名& name){}
inline X::X( const X& t){ memcpy(this, &t, sizeof(X)); }
是否需要 copy constructor
如果一个类涉及 memberwise copy ,就要提供copy constructor的explicit inline函数。
若编译器提供 NRV ,出现返回局部对象,则可使用 NRV 优化,避免调用 copy constructor。

浙公网安备 33010602011771号