执行期语义学——临时性对象

临时对象的生成

 
如果我们有函数如下:

1
T operator+(const T&,const T&);

那么在执行该函数时,可能会生成一个临时对象以存储需要传回的对象。是否会产生临时对象由很多因素决定,其中我们需要的知识点是NRV。

由于市场竞争的关系,大多数编译器均采取了一系列优化策略,以至于如下表达式:

1
T c = a+b;

几乎不可能产生临时对象。但值得注意的是下一种情况——与表达式意义相当的assignment statement:
1
c = a+b;

它会直接导致临时对象的生成:
1
2
3
4
T temp;
temp.operator+(a,b);
c.operator=(temp);
temp.T::~T();

我们可以认为,初始化操作总比赋值操作效率更高。
此外,还有一种生成临时对象的情况:没有出现目标对象:
1
a+b;

这会产生一个临时对象,用以放置运算后的结果。


临时对象的生命期

 
在C++ standard之前,临时对象的生命期并没有明确指定,完全由各编译器生产厂商决定。而C++ standard定义如下:临时对象的被摧毁,应该是对full expression求值过程中的最后一个步骤,该表达式造成临时对象的产生。

什么是full expression?你可以认为是被涵括的表达式中最外围的那个:

1
((objA>1024) && (objB>1024))?objA+objB:foo(objA,objB);

比如该三目运算符表达式即为full expression,任何一个子算式产生的任何一个临时对象,都应当在完整表达式被求值完成后销毁。

此外,C++ standard又有两个特例:

  1. 凡含有表达式执行结果的临时对象,应该存留到object的初始化操作完成为止。
    这种做法提高了初始化效率,防止了另一个临时对象的生成。
  2. 如果一个临时性对象被绑定于一个reference,对象将会被残留,直到被初始化的reference声明结束,或临时对象的生命期结束。