作者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/cn.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