局部堆栈变量成员的返回值优化
Return value optimization of a member of a local stack variable
我有一段通用代码,当实例化时,可以归结为:
struct A{...};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p = g(); // g returns a pair<A, int>, but I am not interested in g
return ret; // RVO :)
};
据我了解,这将适用于 RVO。
问题是,这其他代码会使用 RVO 返回类型A
的对象吗?
A f2(){
std::pair<A, int> p;
p = g();
return p.first; // RVO ?
};
我知道由于返回对象被遮挡,它不会做 RVO,或者编译器可能无法选择"优化"。 但我看不出它不可能的根本原因,换句话说,我认为为了保持一致性,它应该做 RVO(我想要(。
我问的原因,是因为我认为f2
比f1
更优雅的代码。
这个最后一个版本应该做RVO吗?如果是这样,它是否依赖于编译器?
我对 gcc 8.1 的粗略测试表明 RVO 在f2
中不起作用,f3
如下:
struct A{
double something;
A() = default;
A(A const& other) : something(other.something){std::cerr << "cc" << 'n';}
A(A&& other) : something(other.something){std::cerr << "mc" << 'n';}
};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p.first.something = 5.;
return ret; // RVO :)
};
A f2(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return p.first; // no RVO :(
};
A f3(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return std::move(p).first; // no RVO :(
};
int main(){
A a1 = f1(); // prints nothing, RVO
A a2 = f2(); // prints "cc"; no RVO! Why?
A a3 = f3(); // prints "mc" (no much gain in this case); still no RVO!
}
要使 RVO 正常工作,需要在调用方希望找到它的存储中实例化返回值。 也许这是一个寄存器,其名称由调用约定指定,或者它可能在堆栈上。
std::pair<A, int>
本质上是:
struct foo {
A first;
int second;
};
现在,如果返回值需要存储在带有sizeof(A)
的特定位置,但该对的大小更大,则该对不可能存储在那里。 RVO 仍然可以工作的唯一方法是,如果被调用方知道在执行函数时允许破坏返回值后面的sizeof(int)
个字节。 但在这种情况下,该语言可能不需要 RVO,因为它可能无法在每个调用约定中实现。
相关文章:
- 返回值优化:显式移动还是隐式
- 使用 std::p air 进行返回值优化
- C++ 特征图3.5,特征图不使用命名返回值优化?
- 我是否正确测试了返回值优化?
- 使用std::optional时的命名返回值优化
- 找不到使保证返回值优化工作的方法
- 局部堆栈变量成员的返回值优化
- 在没有返回值优化的情况下将两个对象加在一起时,将创建多少个临时对象
- 为什么三元运算符阻止返回值优化
- 实现move构造函数如何影响返回值优化
- 我如何确定将进行返回值优化
- 返回值优化并复制C中的ELINION
- 为什么我在此代码中没有得到返回值优化?
- 了解工厂方法和静态变量赋值的返回值优化 (Visual Studio)
- 返回值优化是否需要声明一个复制构造函数
- 从具有移动语义或返回值优化的函数返回值,但不返回复制构造函数
- RVO(返回值优化)无法解释这个谜团
- 元组/领带的返回值优化
- 无法禁用 std::string 的返回值优化
- 返回值优化和副作用