一、显式的初始化操作
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++对象模型》侯捷 译