编译程序在编译代码时,在求表达式值期间,编译器有时必须创建临时对象(tempeoary object)。和其他别的对象一样,他们需要存储空间,并且必须能够构造和销毁。但是由于这些工作是有编译器自动为我们完成,我们看不到它们——编译器负责决定它们的去留以及它们存在的细节。但是临时量有这样一种情况:它们自动地成为常量。在一般情况下,我们是接触不到临时对象的,而试图改变临时量是错误的,因为这么信息是不可得的。注意:编译器使所有的临时量自动地成为const 。下面通过代码来分析。
上面例子中,f5()返回一个非const X对象,但是在表达式:
f7(f5());
中,编译器必须产生一个临时对象来保存f5()的返回值,使得它能够传递给f7()。如果f7()的参数是按值传递的话,它能很好的工作,然后在f7()中形成那个临时对象的副本,不会的临时对象X产生任何影响。但是,f7()的参数是按引用传递的,这代表它会取临时对象X的地址,又因为f7()所带的参数不是按const引用传递的,所以它允许对临时对象的X进行修改,而编译知道:一旦表达式计算结束,该临时对象就不会再存在,因此,对临时对象X所作的任何修改也将丢失。同时由于所有的临时对象被编译器自动设为const,这种情况会导致编译错误,所以该情况是很容易被发现的。
然而,下面的表达式是合法的,也就是能够编译通过:
f5() = X(1);
f5().modify();
尽管它们能够编译通过,但是实际上存在问题。f5()返回一个X对象,而且对于编译器来说,要满足上面的表达式,它必须创建临时对象来保存返回值。于是,在这两个表达式中,临时对象也被修改,但是在表达式编译过之后,临时对象也将被清除。结果就是丢失了所有的修改,从而代码会产生问题(编译器不会报任何错误)。
另外,如果要将一个临时变量按引用传递给一个函数时,这个函数的参数必须是const。