RVO vs inline

看板C_and_CPP (C/C++)作者 (我要加入劍道社!)時間16年前 (2009/10/20 14:04), 編輯推噓4(4011)
留言15則, 2人參與, 最新討論串1/3 (看更多)
[修正] RVO 不會消除 copy-assignment [/修正]

10/20 13:02,
RVO是因為Compiler會把return value當成參數傳進function
10/20 13:02

10/20 13:03,
裡才會有的optimization吧..如果函式本身inline
10/20 13:03

10/20 13:03,
就不用把return value放在參數列上,自然也不會進行
10/20 13:03

10/20 13:03,
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

10/21 01:46, , 1F
呃,inline的確不會有RVO,因為RVO消除的是obj A=func()中
10/21 01:46, 1F

10/21 01:48, , 2F
obj A=(tmpObj B=func())的tmpObj B這個暫存物件,所以在
10/21 01:48, 2F

10/21 01:49, , 3F
inline下不需要暫存returned value,自然也不用RVO,你所講
10/21 01:49, 3F

10/21 01:53, , 4F
修正,*消除的是拷貝returned value到tmpObj B這個動作
10/21 01:53, 4F

10/21 01:54, , 5F
另外,copy assignment也不會被消除,根據ISO C++ 12.8.15
10/21 01:54, 5F

10/21 01:58, , 6F
能省略的只有從tmpObj copy出來時的copy ctor跟func return
10/21 01:58, 6F

10/21 01:59, , 7F
時,為了承接return值而用來產生tmpObj的copy ctor
10/21 01:59, 7F

10/21 02:17, , 8F
上面那串討論之所以=不會被invoke是因為obj A = B是直接呼
10/21 02:17, 8F

10/21 02:18, , 9F
修正,*obj A = B等於obj A(B) (copy initialize)所以不會
10/21 02:18, 9F

10/21 02:19, , 10F
動到operator=
10/21 02:19, 10F

10/21 10:34, , 11F
obj A = B; 和obj A(B)是不一樣的
10/21 10:34, 11F

10/21 10:35, , 12F
前者是copy initialize,後者是direct initialize
10/21 10:35, 12F

10/21 10:37, , 13F
RVO也不是指省略掉tmpObj那件事
10/21 10:37, 13F

10/21 10:38, , 14F
12.8.15所允許的省略好像沒什麼正式名稱 就copy elison
10/21 10:38, 14F

10/21 10:53, , 15F
^^^^^^^修正一下 是12.8.15的第三個條件
10/21 10:53, 15F
※ 編輯: littleshan 來自: 140.112.29.108 (10/21 11:51)
文章代碼(AID): #1AtLBaLK (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1AtLBaLK (C_and_CPP)