一、程序转化语义
我们所写的代码,在内部是如何转换进行优化;
1、显示的初始化操作
class X{};
X x0;
void foo_bar() {
X x1(x0);
X x2 = x0;
X x3 = X(X0);
}
会经过两个必要从程序转化阶段:
- 重写每一个定义(占用内存的行为),其中的初始化操作会被剥除;
- class的拷贝构造会被安插;
2、参数的初始化
方法一:当一个类对象作为参数,会导入临时性的对象,并调用拷贝构造将其初始化,在将临时的对象交给函数,当离开函数时,将会调用其析构函数释放;
方法二:以拷贝建构方式,把实际参数建构在位置上,记录在堆栈中,在函数返回之前将其析构;
X xx;
foo(xx);
3、返回值的初始化
返回值从局部对象中拷贝返回一般做一个双阶段转换:
- 先加上一个额外参数(reference),用来放置拷贝建构的返回值;
- 在return前插入拷贝构造调用的操作,将要返回的内容拷贝到reference中;
X bar() {
X xx;
return xx;
}
void test(){
X xx = bar();
}
void test2() {
bar().memfunc();
}
4、在使用层面做优化
21. 必须返回对象时,别返回reference
在这个条例上告诉我们如何将一个对象进行返回,效率会比较高;
X bar(const T& y, const T& z) {
return X(y, z);
}
5、在编译器层面做优化
编译器将result参数取代named return value(NRV);
该优化能大大的提供程序效率,但由于时编译器完成,故不能明确知道是否有被优化,且当函数较为复杂时,也难以被优化;
X bar() {
X xx;
return xx;
}
6、是否需要拷贝构造?
class Point3d {
public:
Point3d(float x, float y, float z);
private:
float _x, _y, _z;
};
根据以上的情况下,由于没有【1.类成员2.基类3.虚基类4.虚函数】带有拷贝构造;故在此情况下对成员进行bitwise copy即可;
如果类需要大量的memberwise操作,那么我们需要提供一个explicit inline的拷贝构造;
Point3d::Point3d(const Point3d& rhs) {
memcpy(this, &rhs, sizeof(Point3d));
}
但使用memcpy()还是memset(),只有在类内不含任何由编译器产生的内部成员时才会有效运行;否则将会导致成员初值被改写;
7、成员初始化
4. 确定对象被使用前已先被初始化
class Word {
private:
string name;
int val;
public:
Word() : name(0) {
}
};
|