看板 C_and_CPP 關於我們 聯絡資訊
[修正] RVO 不會消除 copy-assignment [/修正]
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)