【问题标题】:Assignment to const reference in Visual C++ 2013Visual C++ 2013 中 const 引用的赋值
【发布时间】:2016-07-08 08:19:33
【问题描述】:

在 Visual C++ 2013 中,为 const 引用分配临时值是合法的,例如

const int& a = 1;

在一个大型软件项目中,我偶然发现了一行代码需要大约 10 毫秒才能执行:

const std::vector<Item>& desc = (hasItems) ? instance->getItems() : std::vector<Item>();

Item 是一个大约 20 字节的结构,instance->getItems() 返回一个 const std::vector& . 我没有看到为什么这条线的执行时间要超过一瞬间,所以我玩了一下发现

const std::vector<Item>& desc = std::vector<Item>();

也需要 10 毫秒,而

std::vector<Item> items;
const std::vector<Item>& desc = items;

如您所料,几乎是即时的,即 0.00.. 毫秒。

问题是,我可以在现有的复杂软件项目中可靠地重现此问题,但在任何精简的最小示例中,两个版本的运行速度都一样快。我已经在启用了优化的发布版本中测试了所有这些。这些优化之一是否有可能使此异常为 const 引用赋值真的很慢?我真的很想知道是什么导致了这种行为。有人知道是什么原因造成的吗?

接下来,是否有为我意外禁用的 const 引用分配值的警告?如果是,它的 id 是什么?如果编译器可以指出代码中发生这种情况的其他地方,那将会很方便。

编辑:计时是在感兴趣的代码之前和之后使用简单的 CPU 时钟完成的,除以每秒的时钟周期。它不太准确,但可以让您大致了解 10.something 和 0.something 之间的区别。而且它不会以任何方式波动,在这个特定的例子中它是完全可重现的。执行时间有显着差异。

【问题讨论】:

  • 在 C++ 中将临时变量绑定到 const 引用是合法的(实际上是一个非常有用的功能),因此没有警告:herbsutter.com/2008/01/01/…
  • 旁注:这不是作业。
  • 你是如何测量这条线需要 10 毫秒的?
  • 我认为测量有问题。 10 毫秒是很多时间,我相信它与您的计时方法的精度有关(例如,GetTickCount 精度变化高达 16 毫秒或更多)。如果您比较生成的汇编代码,您将确切地看到发生了什么,并且我相信不会有太大差异
  • @PcAF 因为它是一个初始化。

标签: c++ visual-c++ const-reference


【解决方案1】:
const std::vector<Item>& desc =
      (hasItems) ? instance->getItems() : std::vector<Item>();

您可能没有想到,但这一行复制了getItems 的返回值所指的向量。

形式上,由条件运算符执行的类型强制规则共同促成了它。实际上,编译器别无选择:当引用绑定到临时对象时,编译器需要生成代码以在引用最终超出范围时销毁该临时对象 - 但如果可以将相同的引用绑定到有时是临时的,有时是左值。正是为了避免这种情况,编写类型强制规则以确保在您的情况下在条件的两个分支上都创建一个临时的。

这样的事情应该会有所帮助:

std::vector<Item> blank;
const std::vector<Item>& desc =
      (hasItems) ? instance->getItems() : blank;

或者,我想,您可以设计getItems() 以在没有项目时返回对有效空向量的引用,并且不需要调用者跳过箍。为此目的保留一个静态的始终为空的向量变量并非不合理。

【讨论】:

  • @Lightness 好吧,向量可能非常大和/或复制Item 可能非常昂贵。但是,是的,很可能正在使用的时钟的分辨率仅为 10 毫秒。
  • @Ig​​​​​​​​​​​​或:显然Item是“一个大约20字节的结构”:P虽然没有说明它在复制时的作用建设,我们不知道有多少:)
猜你喜欢
  • 1970-01-01
  • 2013-04-19
  • 2016-06-23
  • 2023-04-06
  • 1970-01-01
  • 2013-04-17
  • 2016-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多