我们知道所有程序都是在操作内存.在底层的说就是通过内存来知道要做什么.知道做什么后在从内存中来抽取所要操作的数据,在把结果放到指定内存中!
我们随便的一句代码
a=b+0; //int a,b; 并对a b赋值.
如果是内置类型不用多说编译器采取的是所谓急式评估.就是说见到这样的语句不论上下文如何一定会做写什么.(ADD, MOV)
但如果下面接着在有一句这样的代码.
a=1;
似乎刚才的语句就很多余.
内置类型的存取我们还算能够忍耐.如果是一个对象哪.THIS指针的传递.赋值.等等,效率似乎就没有了.
如果我们能够避免这样的浪费,似乎要比一个说什么事就立刻去做的编译器要更人性化一些.
这就要提到我们的所谓缓式评估
意思就是说直到真的要用到它的时候在做最后的事情
比如对a赋值,用都没有就又一次赋一个新值.那就多余了,我们如果能到用的时候在取做相应的运算就似乎更能提高效率.
例如一个STRING 类,如果想都没想大家一定这么定义:
class string
{
char * p;
public:
string(char *);
char operator[](int);
}
如果这样那么不论是读取还是写都会调用同一个运算符[]函数.即使在类中多了一个const版本.也是针对const对象的.编译器是无法判断读和写操作的.
这样我们就不能写出效率很高的类.因为必须在operator [] 中进行相应的工作并返回一个char
如果想要实现缓式评估.那一般就会定义一个替身类
看看代码
class string
{
char * ptr;
public:
class mychar
{
private:
string & str; //很重要.这就是替身类的重要性.他能更好的区别读和写操作.如果没有STRING 那替身类就失去意义了.
int index;
public :
mychar& operator = (char ); //针对左值
operator char(); //针对右值
mychar(string s, int ii) ;
}
mychar operator [](int );
string(char *);
}
很简陋的一个类 ,但却能说明问题了
当
string s("123");
cout<<s[0]; //因为简陋我们都是假设我们要说明问题的例子
作为一个右值 调用了 string operator[] 产生了一个mychar对象.调用了operator char() 因为我们没定义operator<< 为了区别读和写
s[0]='1';
作为左值.调用了mychar的 operator= 这样就为我们设计一个缓式评估奠定了基础
我们可以在做为右值时采用急式评估.
在作为左值时采用缓式评估
例如作左直时
const char a='1';
s[1]=a;
我们可以简单的返回BOOL 而不返回mychar & 因为我们在函数中operator=里什么都不做 ,或者可以维护一个数据结构, 在operator char()中来取回这个直.
这些数据类型很简单,可能采取缓式评估会很愚蠢.但如果遇到大型软件,大型的数据结构,当他们进行运算或赋值时会很耗效率,采用缓式评估是个好办法!