voidf(C c){ C tmp(); tmp = c; } C f(){ returnC(); }
C c1(1); f(c1); f(C(2)); C c = f();
以上三个f的调用分别输出什么?
下面是结果,
1 2 3 4 5 6 7 8 9 10
c1: C copy from c1, c10000: C c10001: C copy assign from c10000, c10001: operator= ----- c2: C c10002: C copy assign from c2, c10002: operator= ----- c10003: C
因为在这两种情况中发生了copy elision(1,2,3,4)。Copy
elision是一种优化手段,满足特定条件时会发生,当传入的参数是rvalue的时候,无需进行额外的拷贝,直接使用源对象。RVO,全称叫return
value
optimization,编译器会让调用函数在其栈上分配空间,被调函数返回值处的临时对象会在这块内存上构造,进而避免了return时临时对象的拷贝,是copy
elision常见形式。根据返回的对象是否是临时的,有named return
value optimization和return value
optimization。
Copy elision和rvo即使在有可观察的到的side-effects时,也会发生,是As-if
rule的例外中的一种。Dave Abrahams写过pass by value的一系列文章。Ayman
B. Shoukry在这里讨论了nrvo的局限(multiple
return points和conditional initialization)。
c1: C copy from c1, c10000: C c10001: C copy assign from c10000, c10001: operator= ----- c2: C copy from c2, c10002: C c10003: C copy assign from c10002, c10003: operator= ----- c10004: C copy from c10004, c10005: C copy from c10005, c10006: C
stackoverflow的这个答案,给出了Standard
reference和发生copy elision以及return value
optimization常见的例子,下面是搬运例子,