为什么Qt foreach要创建一个容器的副本?
Why does Qt foreach create a copy of the container?
文档只是简单地说明了这一点,但没有解释原因:
Qt在进入a时自动获取容器的副本foreach循环。如果你在迭代时修改容器,那不会影响循环。(如果不修改容器,则复制仍然发生,但由于隐式共享复制容器非常快。)因为foreach创建了一个容器的副本,所以使用变量的非const引用不允许修改原来的容器。它只影响拷贝,这可能不是你想要什么
对我来说,这看起来像是一个自我强加的障碍,使Qt的foreach
比它本来可以更有用-现在你不能用它来修改元素。
我听说boost的foreach
和新的c++ 11 for (auto iter : array)
不执行复制(尽管我不熟悉它们中的任何一个)。
那么复制背后的基本原理是什么呢?
Qt开发人员已经决定用例,当您在循环中修改容器(如在信号处理程序中,也就是插槽等)而不修改原始容器时,它应该防止意外。
用信号槽机制来追踪某些东西是否被修改可能会很棘手。如果使用该容器成员发出信号,则基本上取决于插槽。当然,您总是需要执行外部复制,否则
另一个优点是,您可以将方法调用传递给第二个参数,而无需连续重新求值,因为副本将在第一次创建。如果您问我,这实际上是一个相当简洁的功能,因为您经常希望迭代关联数组键或值,如myHash.keys()
或myHash.values()
。
你可以说boost也有信号槽机制。是的,在我看来,这只是一种不同的方式。他们不必总是做同样的事情。: -)
不同的人对API、样式等有不同的品味。毕竟,您手中有所有的工具来实现您计划处理的任何用例。
你也可以争辩说它可能不是你想要的,你可以做一个显式的复制。这很公平,您可以使用Boost或c++中的标准foreach来做到这一点。
这里的复制没有性能问题,因为对于没有修改的正常迭代,写时复制(也称为隐式共享)已经足够好了。它有一些性能开销,但是可以忽略不计。
对于这样的用例,正确的Qt语义应该是使用迭代器设计模式。例如,Qt的迭代器类都遵循"Java风格"。- 检查注册表项是否链接到(或副本)另一个注册表项
- 当类型适当的构造函数可用时,为什么一个编译器尝试使用已删除的副本构造函数
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- 为什么基于范围的 for 循环中的结构化绑定只是一个副本而不是引用?
- 如果静态变量只为程序的整个部分存储了一个副本,为什么我不能使用静态变量交换 2 个数字?
- 如何告诉 Cppdepend 一个目录有多个本地副本
- 提升线程问题,当一个线程与另一个线程没有相同的副本时如何共享变量?
- 一个静态变量多副本
- 我如何创建一个双重指针的深层副本,涉及其他类(C )
- C++全局常量数组:是否保证合并(优化)到一个副本中
- 为什么主可执行文件和 dlopen 加载的共享库共享命名空间静态变量的一个副本?
- 给定一个填充无符号字符**的 C 函数,如何在没有中间副本的情况下用数据填充 std::vector
- 'std::any_cast' 返回一个副本
- 构造向量时如何摆脱(一个)不必要的副本
- 在一个映射向量上迭代,如果满足条件,则插入一个副本
- unique()似乎正在添加最后一个元素的另一个副本
- c++类的函数是否对所有对象只有一个副本?
- Objective-C:如果我在ARC的函数中返回一个c++对象,它会创建一个副本吗?我是否必须手动释放该副本?
- 用ref. parameter初始化ref. field:是一个副本
- 我如何推堆栈unqiue_ptr不做一个副本