我有一个关于我发现我从函数返回的无序地图的令人沮丧的旅程的故事实际上并不是RVO,即使我确定它是在较早的时间它是不相关的。
有没有办法检查RVO是否在任何给定的功能中发生?或者像我们想要的结果一样列出并且不要做什么?
答案 0 :(得分:4)
是。为类的生命周期方法创建钩子:
#include <iostream>
struct A{
A()
{ std::cout<<"Ctor\n"; }
A(const A& o)
{ std::cout<<"CCtor\n"; }
A(A&& o)
{ std::cout<<"MCtor\n"; }
~A()
{ std::cout<<"Dtor\n"; }
private:
int vl_;
};
A getA(){
A a;
return a;
}
int main(){
A b = getA();
return 0;
}
现在使用RVO,b与a
中的getA
相同,因此您只能看到
Ctor
Dtor
您可以通过添加额外的返回点来抑制RVO:
return a;
return A{a};
或移动:
return std::move(a);
然后你会看到:
Ctor
Mctor
Dtor
Dtor
答案 1 :(得分:2)
您可以验证RVO是否适用于您认为重要的所有地方:
template<typename T>
struct force_rvo: T {
force_rvo() {}
using T::T;
force_rvo(const force_rvo &);
force_rvo(force_rvo &&);
};
force_rvo<std::map<int, int>> f() {
force_rvo<std::map<int, int>> m;
m[17] = 42;
return m;
}
int main() {
auto m = f();
return m[42];
}
force_rvo
类型假装是可复制和可移动的,否则编译器会拒绝return m
。但是如果实际使用了这些中的任何一个,链接器将会失败并告诉您到底发生了什么。包装器是零成本,但需要在调用方和实现方使用它,这可能不是很方便。