【发布时间】:2016-06-19 01:46:18
【问题描述】:
根据this talk 在Qt 容器上使用C++11 范围基础for 时存在一定的缺陷。考虑:
QList<MyStruct> list;
for(const MyStruct &item : list)
{
//...
}
根据谈话,陷阱来自隐式共享。在引擎盖下,基于范围的 for 从容器中获取迭代器。但是因为容器不是 const 的,所以 interator 将是非常量的,这显然足以让容器分离。
当您控制容器的生命周期时,这很容易解决,只需将 const 引用传递给容器以强制它使用 const_iterator 而不是分离。
QList<MyStruct> list;
const Qlist<MyStruct> &constList = list;
for(const MyStruct &item : constList)
{
//...
}
但是,例如容器作为返回值呢?
QList<MyStruct> foo() { //... }
void main()
{
for(const MyStruct &item : foo())
{
}
}
这里发生了什么?容器是否仍被复制?直觉上我会说这是为了避免可能需要这样做?
QList<MyStruct> foo() { //... }
main()
{
for(const MyStruct &item : const_cast<const QList<MyStruct>>(foo()))
{
}
}
我不确定。我知道它有点冗长,但我需要它,因为我在大型容器上大量使用基于范围的 for 循环,所以谈话对我来说是正确的字符串。
到目前为止,我使用辅助函数将容器转换为 const 引用,但如果有更简单/更短的方法来实现相同的效果,我想听听。
【问题讨论】:
-
别担心了。所有 Qt 容器都实现了 COW 模式。在最新版本中,Qt 团队实现了对 C++11 的支持,包括移动 ctor。
-
顺便说一句,尝试
const MyStruct& const item : foo()以 const 样式进行迭代。 -
@SaZ 我会试试你的建议。但是关于 COW,Qt 开发人员在链接的谈话中明确表示从容器创建非常量迭代器意味着它分离。这是有道理的,因为否则他们无法检测到您是否确实使用该迭代器来更改它,只要您能做到这一点就足够了。
-
我真的从来没有遇到过只做
for(const auto& bla : blas)的问题,我什至不认为这可能有问题 -
不应该是
const QList<MyStruct> &constList = list;而不是Qlist<MyStruct> &constList = list;来获取const迭代器并防止分离吗?如果没有,为什么不呢?