推 holymars:RVO是因為Compiler會把return value當成參數傳進function 10/20 13:02
→ holymars:裡才會有的optimization吧..如果函式本身inline 10/20 13:03
→ holymars:就不用把return value放在參數列上,自然也不會進行 10/20 13:03
→ holymars:RVO啊.. 10/20 13:03
RVO 牽涉的不只是 implementation detail
它也會影響到語意
因為它是直接「消除」掉 copy-constructor
即使這個 copy-constructor 具有 side effect 也是一樣會被省略
但 inline function 是不能影響語意的
compiler 不能因為 inline function 就自動省略該有的 constructor
除非說 copy-constructor 是 compiler 自己產生所以它知道內容
上面的例子比較不明顯
我舉 NRVO 來當例子
class Foo {
public:
Foo(const Foo& f)
{
puts("Foo::Foo()");
}
Foo() {}
Foo& operator=(const Foo& f)
{
puts("Foo::operator=()");
return *this;
}
};
inline Foo bar(const Foo& f)
{
Foo tmp = f; // copy constructor
return tmp;
}
int main()
{
Foo a;
Foo b = bar(a);
return 0;
}
如果依照你的說法
因為 inline function 的緣故
在宣告 b 的地方應該會展開成
Foo tmp = a;
Foo b = tmp;
因此會產生兩次 copy-constructor 呼叫
但實際上只會有一次
因為 NRVO 允許 compiler 直接把 tmp 代換成 b 而節省一次 copy-constructor
「即使」在這個情況中因為 inline function 的緣故
使得 b 的位址沒辦法當作參數傳進 function 當中
但 compiler 知道上述的程式碼是「inline function 展開後」的結果
還是有辦法讓 NRVO 起作用的
另一方面
在一般情況下 compiler 不可能會把兩次的 copy-constructor 縮減成一次
因為它不知道你在 copy-constructor 中寫了什麼東西
所以無法保證
Foo tmp = a;
Foo b = tmp;
與
Foo b = a;
的結果是相同的
所以在這個 case 中
用 NRVO 來解釋 compiler 消除掉 copy-constructor 的行為
才是最合理的
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.29.108
→ Chikei:呃,inline的確不會有RVO,因為RVO消除的是obj A=func()中 10/21 01:46
→ Chikei:obj A=(tmpObj B=func())的tmpObj B這個暫存物件,所以在 10/21 01:48
→ Chikei:inline下不需要暫存returned value,自然也不用RVO,你所講 10/21 01:49
→ Chikei:修正,*消除的是拷貝returned value到tmpObj B這個動作 10/21 01:53
→ Chikei:另外,copy assignment也不會被消除,根據ISO C++ 12.8.15 10/21 01:54
→ Chikei:能省略的只有從tmpObj copy出來時的copy ctor跟func return 10/21 01:58
→ Chikei:時,為了承接return值而用來產生tmpObj的copy ctor 10/21 01:59
推 Chikei:上面那串討論之所以=不會被invoke是因為obj A = B是直接呼 10/21 02:17
→ Chikei:修正,*obj A = B等於obj A(B) (copy initialize)所以不會 10/21 02:18
→ Chikei:動到operator= 10/21 02:19
推 holymars:obj A = B; 和obj A(B)是不一樣的 10/21 10:34
→ holymars:前者是copy initialize,後者是direct initialize 10/21 10:35
推 holymars:RVO也不是指省略掉tmpObj那件事 10/21 10:37
→ holymars:12.8.15所允許的省略好像沒什麼正式名稱 就copy elison 10/21 10:38
推 holymars:^^^^^^^修正一下 是12.8.15的第三個條件 10/21 10:53
※ 編輯: littleshan 來自: 140.112.29.108 (10/21 11:51)