622 字
3 分钟

Return Value Optimization

2025-04-10
无标签
文章目录

在函数返回值的传递过程中,可能会触发多次对象的拷贝构造或移动操作。为了减少这些不必要的拷贝,C++ 编译器会采用一些优化技术,如 拷贝省略 (1)、返回值优化 (2)和 命名返回值优化 (3)。

  1. Copy Elision
  2. Return Value Optimization,RVO
  3. Named Return Value Optimization,NRVO

RVO和NRVO的启用条件

RVO 和 NRVO 是编译器自动完成的优化,但是这些优化并不总是启用,具体取决于编译器的实现和配置

  1. 在 C++17 之前,RVO 是一个可选优化,但在 C++17 标准之后,RVO 被强制启用,编译器必须在符合条件的情况下执行拷贝省略。

  2. NRVO 通常依赖于编译器的智能分析,虽然大多数现代编译器都能支持 NRVO,但其效果和激进程度因编译器和版本的不同而有所差异。

按值传递和拷贝省略#

不具名返回值优化#

不具名返回值优化发生在返回一个无名对象或者临时对象,,一般是 Return 语句中直接创建并返回的对象。

URVO 从 C++98 开始已被许可,但是一直到 C++17 编译器才强制返回值优化。

无返回值优化

无返回值优化
Data GetData()
{
return Data{}; // ctro1
// copy ctor2, dtor1
}
int main()
{
Data d = GetData(); // copy ctor3, dtor2
return 0;
// dtor3
}

对象发生多次拷贝。

其中第三次拷贝和赋值右值相关。

有返回值优化

有返回值优化
Data GetData()
{
return Data{}; // ctro1
}
int main()
{
Data d = GetData();
return 0;
// dtor1
}

对象只被构造一次。

具名返回值优化#

具名返回值优化一般发生在返回一个已经创建的对象。

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
在原网站打开

Reference#