一、明确的初始化操作:
X x0;
void foo()
{
X x1(x0);
X x2 = x0;
X x3 = X(x0);
}
对于该程序,必要的程序转换有两个阶段:
1. 重写每一个定义,将初始化的代码给剥夺;
2. 安插拷贝构造函数。
可能程序转换后为:
void foo()
{
//剥夺初始化的操作
X x1;
X x2;
X x3;
//调用拷贝构造函数
x1.X::X(x0);
x2.X::X(x0);
x3.X::X(x0);
}
二、参数的初始化
foo(X x0);
X xx;
foo(xx);
对于这种情况下,编译器会做如下的处理,导入一个临时变量存放xx的值,然后将xx交给foo函数来处理:
X xx;
_temp.X::X(xx);
foo(_temp);
此时foo函数也必须改写为:
foo(X& x0);
早期BorlandC++还是用了另一种方法,那就是不要临时的变量产生,而是通过拷贝构造函数直接将实参拷贝到形参上。
三、返回值的初始化
已知下面的函数定义:
X foo()
{
X xx;
…
return xx;
}
那么程序是如何将xx的值返回的呢?编译器做了一个双阶段转换来完成这个事情:
1.函数加上一个额外的参数,类型是返回类型的引用;
2.在return之前安插一个卡被构造函数操作,将需要传回的对象构造到新增的参数值中。
那么上面的这种情况会被编译器进行转换为:
void foo(X& _result)
{
X xx;
…
_result.X::X(xx);
return;
}
当做出如上转换后,以下的这些调用操作也会被转换:
1.X xx = foo();
//被转换为:
X xx;
foo(xx);
2.foo().fun();
//被转换为:
X_temp;
(foo(_temp),_temp).fun();
3.同样对于函数指针也会被转换:
X(*pf)();
pf = foo;
//转化后:
void (*pf)(X&);
pf = foo;
四、在使用者层面进行代码优化
对于像下面这个函数的函数,程序员可以通过提供特殊的构造函数来优化:
X bar(const T& y, const T& z)
{
X xx;
…//以y和z来处理xx
return xx;
}
如果程序员提供一个可以计算xx的值的构造函数,那么上述代码可以优化为:
X bar(const T& y, const T& z)
{
return X(y,z);
}
这时如果加上函数返回值优化,那么将是如下的情形:
void bar(X& _result, const T& y, const T& z)
{
_result.X::X(y,z);
}
这种优化会带来效率上的提升,但有人却反对这种行为,因为他们认为这样会是这种特殊用途的构造函数大量扩散。
五、编译器NRV优化
关于NRV优化发现一篇讲得不错的博客,直接引用了一下:
http://blog.csdn.net/zha_1525515/article/details/7170059