C++编译器的返回值优化
C++编译器的返回值优化
在对右值概念的学习验证中发现函数构造的实例返回后不会被销毁(尽管已经跳出作用域),而是直接被使用
上代码
#include <iostream>
#include <cstdio>
#include <cassert>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <random>
#include <utility>
#include <string>
using namespace std;
class MoveOrCopy {
private:
int a;
public:
MoveOrCopy() : a(0) {
printf("default consult: %p\n", this);
}
MoveOrCopy(const MoveOrCopy &m) : a(m.a) {
printf("copy consult is called: %p\n", this);
}
MoveOrCopy(MoveOrCopy &&m) noexcept: a(m.a) {
printf("move consult is called: %p\n", this);
}
virtual ~MoveOrCopy() {
printf("MoveOrCopy %p:%d is deleted\n", this, this->a);
}
MoveOrCopy &operator=(const MoveOrCopy &m) {
this->a = m.a;
printf("copy valued is called\n");
}
};
MoveOrCopy create() {
return MoveOrCopy();
}
MoveOrCopy createWithLocal() {
MoveOrCopy t = MoveOrCopy();
return t;
}
MoveOrCopy createCondition(bool b = false) {
return b ? MoveOrCopy() : MoveOrCopy();
}
int main() {
printf("d:\n");
MoveOrCopy d = create();
printf("e:\n");
MoveOrCopy e = createWithLocal();
printf("f:\n");
MoveOrCopy f = createCondition();
return 0;
}
运行结果
d:
default consult: 000000D4B12FFB48
e:
default consult: 000000D4B12FFAD8
move consult is called: 000000D4B12FFB38
MoveOrCopy 000000D4B12FFAD8:0 is deleted
f:
default consult: 000000D4B12FFAC8
move consult is called: 000000D4B12FFB28
MoveOrCopy 000000D4B12FFAC8:0 is deleted
MoveOrCopy 000000D4B12FFB28:0 is deleted
MoveOrCopy 000000D4B12FFB38:0 is deleted
MoveOrCopy 000000D4B12FFB48:0 is deleted
解释
编译器对返回值进行了优化,将临时对象直接构造在 c 对象的空间中,避免了不必要的拷贝或移动操作。
这种优化被称为返回值优化(Return Value Optimization,RVO),它是 C++ 编译器的一种常见优化手段,用于避免不必要的对象拷贝或移动。在这种情况下,即使定义了移动构造函数,编译器也不会调用移动构造函数,而是直接将临时对象构造在 c 对象的空间中。
参考连接
1: 返回值优化