我怎样才能确定一个例程正在利用(N)RVO?

时间:2012-03-08 17:05:10

标签: c++ visual-c++ optimization gcc return-value-optimization

我想确保我的例程尽可能利用(N)RVO。除了解析生成的反汇编之外,还有什么我可以做或检查是否正在使用(N)RVO编译例程?在这一点上,我最感兴趣的是MSVC和GCC。

3 个答案:

答案 0 :(得分:7)

不,不是真的。

但是,您可以在编写代码时遵循指南。


未命名的返回值优化

每次返回临时文件时都会触发此操作,即使在调试模式下也是如此。

return MyObject(....);

命名返回值优化

每次函数总是返回相同的临时对象时,这几乎都会触发:

MyObject func() {
  MyObject result;
  if (...) { return result; }

  result.push(0);
  return result;
}

你可以混合使用它们,但在这种情况下编译器几乎不可能应用RVO:

MyObject func() {
  MyObject result;
  if (...) { return MyObject(...); }

  return result;
}

在这里,一个回归可能会受益于RVO而另一回不会受益。我敢打赌第一个被优化,因为如果你在返回槽中推测性地创建result并且突然需要采用if分支,你就会陷入困境。请注意,只需重新排序语句就可以了:

MyObject func() {
  if (...) { return MyObject(...); }

  MyObject result;

  return result;
}

因此,NRVO的经验法则是return声明和result声明之间不应返回return result;声明,而result声明除了{{1}}之外还返回任何其他声明


如果你遵循这个,你就有可能对你有利。然后,这只是代码审查的问题。

并且您还可以使代码更容易阅读,因为在知道您确实需要变量之前不会声明变量!

答案 1 :(得分:2)

您可以向析构函数添加调试方法:

struct A
{
   ~A() { cout << "destructor called"; }
};

A foo()
{
   A a;
   return a;
}

如果调用析构函数,则可能未应用RVO。

答案 2 :(得分:1)

我能想到的可能方法是:

  1. 在你的类中实现一个引用计数机制,它跟踪通过类创建的实例的数量,就像shared_ptr一样,这样你可以检测你的类的额外副本如果没有发生复制,则创建和删除。

  2. 您可以简单地将调试跟踪放在类的复制构造函数和析构函数中,如果没有发生复制省略,您会看到许多连续的复制构造函数和析构函数调试跟踪。