c++ RVO 和 NRVO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linux_vae/article/details/79369265

在查看std::move是否有必要在return localvar 中使用的时候,查看到了RVO和NRVO,因为std::move总是会调用移动构造函数所以会增加一次构造。

关于RVO和NRVO

RVO (return value optimization) 和NRVO (named return value optimization) 是C++在处理 “返回一个class object的函数” 时常用的优化技术,主要作用就是消除临时对象的构造和析构成本

经过测试,gcc编译器在debug和release模式下均支持NRVO,VS在debug模式下不支持NRVO,仅支持RVO,而在release模式下也支持NRVO

参考文章 蓝大@蓝色的这篇文章

RVO V.S. std::move 讲解的很到位。

C++的拷贝构造函数的调用时机? - Skillness 的回答 

Return value optimization 维基百科

首先,关于C++标准中的这段话,在copy elision中找到的关于RVO的描述如下

  • When a nameless temporary, not bound to any references, would be moved or copied into an object of the same type (ignoring top-level cv-qualification), the copy/move is omitted. When that temporary is constructed, it is constructed directly in the storage where it would otherwise be moved or copied to. When the nameless temporary is the argument of a return statement, this variant of copy elision is known as RVO, "return value optimization".

翻译一下:

当一个未命名且未绑定到任何引用的临时变量被移动或复制到一个相同的对象时,拷贝和移动构造可以被省略。当这个临时对象在被构造的时候,他会直接被构造在将要拷贝/移动到的对象。当未命名临时对象是函数返回值时,发生的省略拷贝的行为被称为RVO,"返回值优化"。

代码:
#include <iostream>
using namespace std;
struct C {
	C() { std::cout << "A Construct.\n"; }
	~C(){ std::cout << "A DisConstruct.\n"; }
	C(const C&) { std::cout << "A copy was made.\n"; }
	//C(C&&) { std::cout << "A move was made.\n"; }
};
template<typename T>
T f() {
	T c;
	//return std::move(c);
	return c;
}
int main() {
	std::cout << "Hello World!\n";
	C obj = f<C>();
	//f<C>();
	return 0;
}

在vs debug(RVO)中输出:


在vs release中输出:


在linux g++下输出


不使用RVO和NRVO的结果:


那么RVO编译器是怎么优化的呢

T f() {
	T c;
	return c;
}

void f(T& _c) {
	T c;
        _c.T::T(c);//拷贝构造调用
	return ;
}
主函数:

C obj = f<C>();
C obj;//定义而不构造
(f<C>(obj),obj);

显然如果调用方式为f<C>(),不赋值的话RVO没有用

而NRVO的优化,即直接用临时对象的引用替换了原本的返回变量,并在函数体内调用普通构造函数进行构造

void f(T& _c) {
	_c.T::T();//优化拷贝构造
	return ;
}






猜你喜欢

转载自blog.csdn.net/linux_vae/article/details/79369265
RVO