【问题标题】:GCC NRVO/RVO warningGCC NRVO/RVO 警告
【发布时间】:2013-12-19 05:41:01
【问题描述】:

是否有任何警告,让我们知道 NRVO/RVOGCC 中是否执行?

我发现-fno-elide-constructors关闭了NRVO/RVO,但是NRVO/RVO有自己的条件发生,有时不发生。有必要知道 NRVO/RVO 是否发生,以便了解何时发生额外的复制构造。

我对编译时特性特别感兴趣。如果有一些特定的#pragma GCC...(它会在其自身之后立即激活诊断)或使用静态断言机制的东西,那就太好了。

【问题讨论】:

  • 据我所知,编译器不会通知您这种优化,尤其是它们是否发生以及何时发生以及为什么发生,但有一些指导方针stackoverflow.com/questions/7320520/…
  • 鉴于-Winline等警告的存在,这很奇怪。
  • -Wdisabled-optimization 什么都不给?然后你仍然可以查看-fdump-ipa-all 的输出是否告诉你什么。
  • @Damon 如何检查-Wdisabled-optimization 是否可行?我无法使用-fdump-tree-nrv 获取任何.nrv 输出文件,而且似乎-fopt-info-nrv-missed/-fopt-info-missed-nrv 不存在。
  • 对我有用,它将.nrv 文件放在.o 文件旁边——更大的挑战是阅读这些混乱,因为它们并不是非常人性化的文件。我自己只使用过-Wdisabled-optimization 一次或两次,因为“噪音”太烦人了,几乎没有什么好处。不过,当时它似乎工作得很好(就它的作用而言)。

标签: c++ gcc g++ copy-elision


【解决方案1】:

我不知道任何 gcc 特定的诊断消息或其他可以轻松解决您的任务的方法。正如您所发现的,-fno-elide-constructors 将禁用复制/移动省略,因此您将确定至少在这种情况下不会发生 (N)RVO。

但是,快速浏览this C++11 working draft 第 12.8 节中的第 31 段指出:

当满足某些条件时,允许省略实现 类对象的复制/移动构造,即使复制/移动 对象的构造函数和/或析构函数有副作用。在 在这种情况下,实现会处理 省略复制/移动操作只是两种不同的引用方式 到同一个对象,并且该对象的销毁发生在 在这两个物体将被摧毁的后期 没有优化。这种复制/移动操作的省略, 称为复制省略,在以下情况下是允许的 (可以合并以消除多个副本):

  • 在具有类返回类型的函数的 return 语句中,当表达式是非易失性自动对象的名称时(其他 比函数或 catch-clause 参数)具有相同的 cv-unqualified type 作为函数返回类型,可以进行复制/移动操作 通过将自动对象直接构造到 函数的返回值

...

  • 当尚未绑定到引用的临时类对象时 (12.2) 将被复制/移动到具有相同引用的类对象 cv-unqualified 类型,复制/移动操作可以省略 将临时对象直接构造到 省略复制/移动

...

当复制/移动省略发生时,本地自动对象与临时(返回)对象相同,而临时(返回)对象又与“存储”对象(存储返回值的位置)相同。因此本地自动对象与存储对象相同,这意味着指针比较将等于 true。一个简单的例子来证明这一点:

#include <iostream>
#include <vector>

std::vector<int> testNRVO(int value, size_t size, const std::vector<int> **localVec)
{
   std::vector<int> vec(size, value);

   *localVec = &vec;

   /* Do something here.. */

   return vec;
}

int main()
{
   const std::vector<int> *localVec = nullptr;

   std::vector<int> vec = testNRVO(0, 10, &localVec);

   if (&vec == localVec)
      std::cout << "NRVO was applied" << std::endl;
   else
      std::cout << "NRVO was not applied" << std::endl;
}

启用/禁用-fno-elide-constructors 会按预期更改打印的消息。注意:在最严格的意义上,指针比较可能取决于未发生 (N)RVO 时的未定义行为,因为本地自动对象不存在。

进行指针比较会增加麻烦,但具有编译器独立性的优势。

【讨论】:

  • 不获取本地地址有时会妨碍优化?
猜你喜欢
  • 2018-08-03
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
相关资源
最近更新 更多