为什么Qt foreach会创建容器的副本?

时间:2014-05-12 15:19:49

标签: c++ qt foreach containers qtcore

文档只是states that it does,但没有解释原因:

  

Qt在进入时会自动获取容器的副本   foreach循环。如果您在迭代时修改容器,那就是   不会影响循环。 (如果不修改容器,则复制   仍然发生,但由于隐含共享复制容器   非常快。)因为foreach创建了一个容器的副本,使用   变量的非const引用不允许您修改   原装容器。它只影响副本,这可能不是   你想要什么。

对我而言,这看起来像是一种自我强加的障碍,使得Qt的foreach没有那么有用 - 现在你不能用它来修改元素。

我听说过,foreach和新版C ++ 11 for (auto iter : array)没有执行副本(虽然我对其中任何一个都不熟悉)。

复制背后的理由是什么?

1 个答案:

答案 0 :(得分:5)

Qt开发人员已决定在不修改原始容器的情况下修改循环中的容器(如在信号处理程序,例如.k.a.slot等中)时应避免意外的用例。

使用信号槽机制来追踪某些内容是否被修改可能会很棘手。如果您使用该容器成员发出信号,它将基本上由插槽决定。可以肯定的是,你总是需要进行外部复制。

另一个优点是您可以将方法调用传递给第二个参数而无需连续重新评估,因为第一次创建副本。如果您问我,这实际上是一个非常简洁的功能,因为通常,您希望迭代关联数组键或myHash.keys()myHash.values()之类的值。

你可能会认为boost也有信号槽机制。是的,在我看来,这只是一种不同的做法。他们不必一直这样做。 : - )

不同的人对API,样式等有不同的品味。毕竟,您掌握了所有工具,以实现您计划处理的任何用例。

你也可以说它可能不是你想要的,你会做一个明确的副本。这是公平的,你可以使用Boost或C ++中的标准foreach。

此处没有关于副本的性能问题,因为对于正常迭代而没有修改,写入时复制(a.k.a。隐式共享)就足够了。它有一些性能开销,但可以忽略不计。

这种用例的正确Qt语义是使用迭代器设计模式。例如,Qt在" Java样式"之后的所有地方都有迭代器类。