Return Value Optimization
在函数返回值的传递过程中,可能会触发多次对象的拷贝构造或移动操作。为了减少这些不必要的拷贝,C++ 编译器会采用一些优化技术,如 拷贝省略 (1)、返回值优化 (2)和 命名返回值优化 (3)。
- Copy Elision
- Return Value Optimization,RVO
- Named Return Value Optimization,NRVO
RVO和NRVO的启用条件
RVO 和 NRVO 是编译器自动完成的优化,但是这些优化并不总是启用,具体取决于编译器的实现和配置
在 C++17 之前,RVO 是一个可选优化,但在 C++17 标准之后,RVO 被强制启用,编译器必须在符合条件的情况下执行拷贝省略。
NRVO 通常依赖于编译器的智能分析,虽然大多数现代编译器都能支持 NRVO,但其效果和激进程度因编译器和版本的不同而有所差异。
按值传递和拷贝省略¶
不具名返回值优化¶
不具名返回值优化发生在返回一个无名对象或者临时对象,,一般是 Return
语句中直接创建并返回的对象。
URVO 从 C++98 开始已被许可,但是一直到 C++17 编译器才强制返回值优化。
具名返回值优化¶
具名返回值优化一般发生在返回一个已经创建的对象。
MSVC默认不开启具名返回值优化,如果需要开启优化,需要在 /O2
下编译。
容器返回值优化¶
对于容器来说,若整个容器发生拷贝,代价很高。
因此,非常有必要考虑返回值优化。C++17 开始,强制对容器进行返回值优化。
容器返回值优化
std::vector<Data> GetDataContainers() {
//!!! case 1
// return std::vector<Data>{Data{}}; // ctor 1, copy ctor 2, dtor 1
//!!! case 2
std::vector<Data> vec{Data{}}; // ctor 1, copy ctor 2, dtor 1
return vec;
}
int main() {
auto d = GetDataContainers();
return 0;
} // dtor 2