3

在 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< Item>&。我没有看到为什么这条线的执行时间应该超过一瞬间,所以我玩了一下,发现

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

也需要 10 毫秒,而

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

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

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

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

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

4

1 回答 1

2
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()在没有项目时返回对有效空向量的引用,并且不需要调用者跳过箍。为此目的保留一个始终为空的静态向量变量并非不合理。

于 2016-07-08T14:41:02.767 回答