作者yam276 (史萊哲林的優等生)
看板Marginalman
標題[閒聊] 每日C++小秘密(3):Copy Elision 與 RVO
時間Tue Oct 29 18:19:24 2024
他們是什麼?
Copy Elision 和 Return Value Optimization(RVO)是編譯器的最佳化技術,
它們的目標是減少不必要的物件建構和拷貝,以提升程式效能。
Copy Elision
Copy Elision 是C++標準允許的最佳化手段,
避免了多次呼叫拷貝建構函式(或移動建構式)。
有些情況下編譯器甚至會跳過呼叫任何建構式,
而是直接在目標位置上建構物件。
RVO (Return value optimization)
RVO 是Copy Elision的一個特例。
當函式回傳 Local 物件時,
RVO 允許直接在呼叫者的記憶體空間建構物件,
而不是先在函式內建構,然後再拷貝到呼叫者。
原因
C++ 裡面一個物件都會有以下成員:
建構式 (Constructor)
複製建構式 (Copy Constructor)
移動建構式 (Move Constructor)
解構式 (Destructor)
沒有RVO的情況,可能在回傳物件的過程會呼叫非常多次的各種建構式解構式,
造成資源的浪費。
Code:
#include <iostream>
class A {
public:
A() { std::cout << "Constructor\n"; }
A(const A&) { std::cout << "Copy Constructor\n"; }
A(A&&) { std::cout << "Move Constructor\n"; }
~A() { std::cout << "Destructor\n"; }
};
A func() {
A a; // 在此地建構物件a
return a; // 觸發RVO,直接將a建構在呼叫者的記憶體中
}
int main() {
A b = func(); // 若RVO啟用,不會有多餘的拷貝或移動操作
return 0;
}
若啟用了RVO:
Constructor
Destructor
若RVO被關閉:
Constructor
Copy Constructor (或 Move Constructor)
Destructor
Destructor
而在Modern C++,自C++17起,RVO變得強制性(Mandatory RVO),
編譯器在大部分情況下必須強制進行RVO。
但RVO,真的好嗎?
我在這邊引用一段話CSDN看到的結論:
尽管C++11以上标准提出“复制省略(copy elision)”优化策略,并且GCC等主流编译器均
支持该优化,但我强烈不建议使用该技术。
我们在使用C++语言时,必须牢记,返回值必须是int、bool、枚举或指针等轻量级原生
(lightweight primitive)数据类型。
如果确实需要返回大型数据,请使用引用或指针作为输出参数返回,而不是通过return语
句返回。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.32.48.170 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/Marginalman/M.1730197166.A.B21.html
1F:推 DJYOMIYAHINA: 剩我都直接return整坨了 10/29 18:22
2F:推 CCapocalypse: 大師 10/29 18:22
3F:推 nh60211as: 大師 10/29 18:24
4F:→ nh60211as: 但我强烈不建议使用该技术 => 為啥啊 10/29 18:25
5F:→ yam276: 因為這用法很高階語言 不夠輕量 通常大的struct都用heap傳 10/29 18:26
6F:推 ILoveErr: 大師 10/29 18:26
7F:→ yam276: 像是你new或make_shared之後把指標傳出去 10/29 18:26
8F:→ yam276: 那等於你只是給了鑰匙給別人而不是整個房間丟出去 10/29 18:27
9F:推 sustainer123: 大師 10/29 18:35
10F:推 SecondRun: 大師 10/29 18:44
11F:推 deatheo: 大師 10/29 20:39