有没有办法检查是否应用了RVO?

use*_*993 7 c++11

我讲述了一个令人沮丧的旅程的故事,我发现我从一个函数返回的无序地图实际上并不是RVO,即使我确定它是在较早的时间它是无关紧要的.

有没有办法检查RVO是否在任何给定的函数中发生?或者像一个做的列表并且不要遵循以获得我想要的结果?

PSk*_*cik 6

是的。为类的生命周期方法创建钩子:

#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;
}
Run Code Online (Sandbox Code Playgroud)

现在使用 RVO,b 和ain是同一个对象,getA所以你只会看到

Ctor
Dtor 
Run Code Online (Sandbox Code Playgroud)

您可以抑制 RVO,例如,通过添加额外的返回点:

 return a;
 return A{a};
Run Code Online (Sandbox Code Playgroud)

或移动:

return std::move(a);
Run Code Online (Sandbox Code Playgroud)

然后你会看到:

Ctor
Mctor
Dtor
Dtor 
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法在较低级别上做到这一点?即不改变代码? (2认同)

Con*_*nov 5

您可以验证 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];
}
Run Code Online (Sandbox Code Playgroud)

force_rvo类型假装是可复制和可移动的,否则编译器将拒绝return m。但如果实际使用其中任何一个,链接器将失败并告诉您到底发生在哪里。包装器是零成本的,但需要在调用方和实现方都使用它,这可能不是很方便。