C++标准规定,将一个class object作为参数传递给一个function,等效于以下的初始化形式:
X xx = arg;
这里,xx表示的是形式参数(formal argument)或是返回值(return value),arg表示的是实际参数(actual argument)。因此,假定有一个函数
void foo(X x0);
并有如下的调用:X xx;
// ...
foo( xx );
这时候就需要x0这个局部实例以xx来memberwise initialized。// ...
foo( xx );
一种实现的策略就是引入一个临时的对象(temporary object),调用拷贝构造函数(copy constructor)来初始化这个对象,并将它传给function。例如,将以上的代码片段采用这种策略做转换,得到的伪代码如下:
// Pseudo C++ code
// compiler generated temporary
X __temp0;
// compiler invocation of copy constructor
__temp0.X::X ( xx );
// rewrite function call to take temporary
foo( __temp0 );
// compiler generated temporary
X __temp0;
// compiler invocation of copy constructor
__temp0.X::X ( xx );
// rewrite function call to take temporary
foo( __temp0 );
但是,这个转换仅仅才完成了一半。为什么呢?因为foo()的声明中,临时对象会先以class X的copy constructor正确地初始化,再被bitwise copy到局部变量x0中!因此,foo()的声明也要做转换,不再使用一个对象实例作为参数,而使用对于class X的一个对象引用作为参数:
void foo( X& x0 );
如果class X声明了一个析构方法,那么在foo方法调用结束之后,临时对象的析构方法会被调用。
另一种实现是将在函数激活的时候,直接以拷贝构造在stack栈上作出实际参数。在函数调用返回之前,局部对象的析构函数会被调用。Borland C++编译器,就采用了这种策略,不过它也提供了一个编译器选项,可以实现第一种策略,这主要是为了兼容早期编译器的实现。
评论